libpipe 0.7__tar.gz → 0.9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
libpipe-0.9/PKG-INFO ADDED
@@ -0,0 +1,85 @@
1
+ Metadata-Version: 2.4
2
+ Name: libpipe
3
+ Version: 0.9
4
+ Summary: Pipeline orchestration and node management utilities
5
+ License-Expression: GPL-3.0-or-later
6
+ License-File: LICENSE
7
+ Author: Florent Mertens
8
+ Author-email: florent.mertens@gmail.com
9
+ Requires-Python: >=3.10,<4.0
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Provides-Extra: dev
17
+ Provides-Extra: docs
18
+ Requires-Dist: asyncssh (>=2.0)
19
+ Requires-Dist: click (>=8.0)
20
+ Requires-Dist: myst-parser (>=2) ; extra == "docs"
21
+ Requires-Dist: progressbar2 (>=3.40)
22
+ Requires-Dist: pydata-sphinx-theme (>=0.15) ; extra == "docs"
23
+ Requires-Dist: pytest (>=8.0) ; extra == "dev"
24
+ Requires-Dist: pytest-cov (>=5.0) ; extra == "dev"
25
+ Requires-Dist: ruff (==0.16.1) ; extra == "dev"
26
+ Requires-Dist: sphinx (>=7) ; extra == "docs"
27
+ Requires-Dist: sphinx-click (>=6) ; extra == "docs"
28
+ Requires-Dist: toml (>=0.10)
29
+ Project-URL: Documentation, https://libpipe.readthedocs.io
30
+ Project-URL: Homepage, https://gitlab.com/flomertens/libpipe
31
+ Project-URL: Issues, https://gitlab.com/flomertens/libpipe/-/issues
32
+ Project-URL: Repository, https://gitlab.com/flomertens/libpipe
33
+ Description-Content-Type: text/markdown
34
+
35
+ Libpipe
36
+ =======
37
+
38
+ Common pipeline framework and library
39
+
40
+ Installation
41
+ ------------
42
+
43
+ libpipe can be installed via pip:
44
+
45
+ $ pip install libpipe
46
+
47
+ and requires Python 3.10 or higher.
48
+
49
+ Worker pools on a Slurm cluster
50
+ -------------------------------
51
+
52
+ A `WorkerPool` runs its tasks locally, on other hosts over SSH, or through Slurm with the
53
+ host `slurm`: each task is then started with `srun`, as a job of its own when the pool runs
54
+ on a login node, as a job step inside an allocation (`salloc`, `sbatch`).
55
+
56
+ pool = worker.WorkerPool(['slurm'], name='Imaging', max_tasks_per_worker=8,
57
+ slurm_options='-p regular --mem=200G --time=24:00:00')
58
+
59
+ `max_tasks_per_worker` is the number of jobs in flight. The srun options (partition,
60
+ account, resources) come from `slurm_options`, or from the `LIBPIPE_SLURM_OPTIONS`
61
+ environment variable; `max_time` becomes the job time limit when the options set none.
62
+ Host constraints (`run_on_host`) do not apply: Slurm places the tasks, so the data must be
63
+ on a file system shared with the compute nodes.
64
+
65
+ With `slurm_nodes`, a pool on a login node requests one allocation of up to that many nodes
66
+ when its first task starts, runs each task as a job step in it (`srun --jobid --exact`), and
67
+ releases it at the end, or after 10 minutes without step. Slurm packs the steps on the nodes
68
+ from their CPUs and memory, given by the category of the task; a step starts when the
69
+ allocation has its CPUs free, so that no srun waits polling the controller:
70
+
71
+ pool = worker.WorkerPool(['slurm'], name='Cubes', slurm_nodes=4,
72
+ resources={'heavy': {'cpus': 12, 'mem': '40GB'}})
73
+ pool.add('pstool gen_vis_cube ...', category='small', label='gen_vis_cube')
74
+
75
+ The categories (`DEFAULT_RESOURCES`) are `small` (1 CPU, 2 GB), `medium` (4, 8 GB),
76
+ `high_mem` (2, 16 GB), `cpu` (12, 8 GB) and `heavy` (12, 40 GB, the default), the others capped
77
+ at `heavy`; a step also gets the matching `OMP_NUM_THREADS`. The options apply to the jobs and
78
+ the allocation, not to the steps. Inside an allocation started by hand, the tasks are job
79
+ steps with these resources as well.
80
+
81
+ Slurm does not necessarily limit the memory of a job step: the memory of a category must stay
82
+ above the peak memory of its tasks. The local and Slurm pools measure each task (wall time,
83
+ CPU time, peak RSS, in its log file), and `WorkerPoolReport.usage_lines()` summarises them per
84
+ task type (`label`).
85
+
libpipe-0.9/README.md ADDED
@@ -0,0 +1,50 @@
1
+ Libpipe
2
+ =======
3
+
4
+ Common pipeline framework and library
5
+
6
+ Installation
7
+ ------------
8
+
9
+ libpipe can be installed via pip:
10
+
11
+ $ pip install libpipe
12
+
13
+ and requires Python 3.10 or higher.
14
+
15
+ Worker pools on a Slurm cluster
16
+ -------------------------------
17
+
18
+ A `WorkerPool` runs its tasks locally, on other hosts over SSH, or through Slurm with the
19
+ host `slurm`: each task is then started with `srun`, as a job of its own when the pool runs
20
+ on a login node, as a job step inside an allocation (`salloc`, `sbatch`).
21
+
22
+ pool = worker.WorkerPool(['slurm'], name='Imaging', max_tasks_per_worker=8,
23
+ slurm_options='-p regular --mem=200G --time=24:00:00')
24
+
25
+ `max_tasks_per_worker` is the number of jobs in flight. The srun options (partition,
26
+ account, resources) come from `slurm_options`, or from the `LIBPIPE_SLURM_OPTIONS`
27
+ environment variable; `max_time` becomes the job time limit when the options set none.
28
+ Host constraints (`run_on_host`) do not apply: Slurm places the tasks, so the data must be
29
+ on a file system shared with the compute nodes.
30
+
31
+ With `slurm_nodes`, a pool on a login node requests one allocation of up to that many nodes
32
+ when its first task starts, runs each task as a job step in it (`srun --jobid --exact`), and
33
+ releases it at the end, or after 10 minutes without step. Slurm packs the steps on the nodes
34
+ from their CPUs and memory, given by the category of the task; a step starts when the
35
+ allocation has its CPUs free, so that no srun waits polling the controller:
36
+
37
+ pool = worker.WorkerPool(['slurm'], name='Cubes', slurm_nodes=4,
38
+ resources={'heavy': {'cpus': 12, 'mem': '40GB'}})
39
+ pool.add('pstool gen_vis_cube ...', category='small', label='gen_vis_cube')
40
+
41
+ The categories (`DEFAULT_RESOURCES`) are `small` (1 CPU, 2 GB), `medium` (4, 8 GB),
42
+ `high_mem` (2, 16 GB), `cpu` (12, 8 GB) and `heavy` (12, 40 GB, the default), the others capped
43
+ at `heavy`; a step also gets the matching `OMP_NUM_THREADS`. The options apply to the jobs and
44
+ the allocation, not to the steps. Inside an allocation started by hand, the tasks are job
45
+ steps with these resources as well.
46
+
47
+ Slurm does not necessarily limit the memory of a job step: the memory of a category must stay
48
+ above the peak memory of its tasks. The local and Slurm pools measure each task (wall time,
49
+ CPU time, peak RSS, in its log file), and `WorkerPoolReport.usage_lines()` summarises them per
50
+ task type (`label`).
@@ -0,0 +1,25 @@
1
+ '''Run a command, then report its wall time, CPU time and peak memory on stderr, for the task
2
+ accounting of WorkerPool.
3
+
4
+ Usage: python taskrun.py COMMAND [ARGS...]'''
5
+
6
+ import resource
7
+ import subprocess
8
+ import sys
9
+ import time
10
+
11
+ MARKER = '[libpipe] usage '
12
+
13
+
14
+ def main():
15
+ start = time.monotonic()
16
+ returncode = subprocess.call(sys.argv[1:])
17
+ # Of the waited descendants: peak RSS of the largest one, CPU time of all
18
+ usage = resource.getrusage(resource.RUSAGE_CHILDREN)
19
+ print(f'{MARKER}wall={time.monotonic() - start:.1f} cpu={usage.ru_utime + usage.ru_stime:.1f} '
20
+ f'maxrss_kb={usage.ru_maxrss}', file=sys.stderr, flush=True)
21
+ sys.exit(returncode if returncode >= 0 else 128 - returncode)
22
+
23
+
24
+ if __name__ == '__main__':
25
+ main()