The Persistent Queue - perqueue
The aim of the perqueue package is to be a lightweight but powerful workflow manager that wraps the myqueue package. Thus, perqueue can make use of all the schedulers that myqueue already supports.
The attractive points of using perqueue for workflow management instead of using the workflow eco-system already present in myqueue comes down to at least five areas, where the two differ:
perqueuehas internal data storage for all submitted tasks, which means that data can be returned from each task and stored with it. This makes it a lot simpler to propagate data from one task to another, and thus dependencies can much more easily access the results or parameters of their dependants.- Tasks submitted through
perqueueare only submitted to the job scheduling system (by use ofmyqueue) once all dependencies of that task are met. Therefore, large volume parallel jobs can be submitted without worrying about restrictions to the max number of jobs allowed. - Any python file can be run through
perqueuewithout having to touch any environment variables nor installing it as a package. The code is instead run withrunpy, and only needs amain()function, which is described in Format of Code. - While
myqueuemarks each task asdone,running,failedandtimed-out,perqueuealso distinguishes between whether a task has met a given criteria or not. Thus, if a workflow is of a filtering nature, where the specific result of a calculation determines whether the following steps are performed,perqueuecan easily stop the workflow at that point. - Dynamic workflows can be implemented for cyclical and variable width cases. Additionally, dynamic workflow branching is supported.
Some of the upcoming features in the next releases are going to be huge improvements over myqueue, and they will include:
- Extending workflows after submission
Installing perqueue
Since the package is not on PyPI, you need to install it directly from GitLab. At the moment, this is achieved by cloning the project and installing it from source. In the future, there will hopefully be pre-compiled wheels, that one can install directly.
Install from GitLab
If you are a regular user of perqueue, you can use the pip-git interface to install directly from GitLab:
pip install git+https://gitlab.com/asm-dtu/perqueue.git
Otherwise, if you are installing it as a developer, you can do an editable install. Start by cloning the project using the SSH protocol (this requires setting up SSH keys):
git clone git@gitlab.com:asm-dtu/perqueue.git
Then move into the newly created perqueue directory and in there run:
pip install -e .
The
-ecreates an editable install. The install will be static, if it's omitted.
Either way will install perqueue and its dependencies (which can be found in pyproject.toml). The next thing to do is set up myqueue, if this hasn't already been done. A guide to this can be found in their documentation.
Once perqueue has been installed, you need to initialize the queue database that it relies on. You can do this by running the following command in the project directory:
pq init
This will initialize a queue database in the current directory.
You can find all the options of the
pqCLI by callingpq --help
Installing a Specific Version from GitLab
If you need to install a specific release of perqueue, you can clone the repository with the following command instead:
git clone -b <release-tag> --single-branch git@gitlab.com:asm-dtu/perqueue.git
Thereafter, you can just follow the rest of the installation instructions.
Using the perqueue package
The perqueue package is designed to run on top of myqueue, so ensure that you have a basic understanding of that package before venturing too far with perqueue.
To use perqueue, you define a script that contains all the steps of the current workflow. The workflow must correspond to a Directed Acyclic Graph, which means that there can't be any cycles in the workflow. To introduce cyclicity, you make use of the CyclicalGroup.
Each step is defined as a Task, which corresponds to a single python script. The dependencies between them are defined with Workflows, that use the DiGraph format from networkx to describe the dependency graph. Each script must have a main() function, which works as an entry point. This is described in Format of Code.
The Command Line Interface
The package includes a command line interface to make it simpler to handle certain operations of the package. Calling pq --help will give you an overview of the functionality, and each subcommand also has help text.
The most commonly used subcommands are list, modify and resubmit. These list the tasks of the queue, modify the arguments or resources of a job, and resubmit a job that has failed or timed out, respectively.
These subcommands can filter the affected tasks directly regarding the perqueue ID, their (most recent) MyQueue ID, the name of the code (or Task) and the state of the task.
For the IDs, you can specify either a single integer, a comma-separated list of integers (e.g., 1,2,3,4 - no white-space) or an inclusive range of integers (1-10).
The name supports both globbing and regex, such that you don't have to specify the full name.
Do beware that when using globbing or regex, you'll have to quote the string, e.g.,
pq list -n "cod*py". Otherwise things will break.
Creating Workflows with PerQueue
Any workflow that utilizes perqueue is defined in a python script like the one shown here, which you run as a normal Python script for submission:
from pathlib import Path
from perqueue import PersistentQueue, Task, Workflow
code_path<n>: str | Path
args<n>: dict
resources<n>: str = "cores:partition:procs:time" # Uses same format as MyQueue
task1 = Task(code_path1, args1, resources1, name="start")
task2 = Task(code_path2, args2, resources2, name="left")
task3 = Task(code_path3, args3, resources3, name="right")
with PersistentQueue() as pq:
pq.submit(Workflow({task1: [], task2: [task1], task3: [task1]}))
# This submits a workflow with the following structure
# start
# ______|______
# | |
# left right
📑 When adding tasks to the
PersistentQueue, one must always use it in awithblock! This ensures that the jobs are only submitted if no errors occur during the submission. NB:perqueuethrows an Exception, if the context manager way is not used.
Note that the code argument is either a str or a pathlib.Path with the relative path from the current, or an absolute path, that points to the python file containing the code of the task.
Examples of actual workflows can be found in the examples folder.
Format of Code
To make code work with the perqueue workflow, it needs just 1 thing:
The code must have a main function with the signature
def main(arg1=..., ..., **kwargs) -> Tuple[bool, Optional[dict]]:
Which in plain speak means, that the function can take any number of key-value parameters (but no non key-value parameters), and must return a tuple. The first element of this tuple must be a boolean (either True or False), and the second element must be either None or a dict.
Data Passing
A nice feature of perqueue is the automatic passing of data from dependencies to the dependants. This means that any data returned as part of the dict of a task is automatically passed on to its child tasks. Let's illustrate this with an example:
Task2 depends on Task1. The dict returned from Task 1 is {"maximum_value": 42, "path_to_data": "path/to/file"}. Thus, the main function of Task2 can be def main(maximum_value=None, **kwargs): and inside the scope of main, the maximum_value will have been set to 42, and kwargs will be {"path_to_data": "path/to/file", ...}. This considerably simplifies passing data between tasks.
Task1(**kwargs)
|
{"maximum_value": 42, "path_to_data": "path/to/file"}
|
v
Task2(maximum_value, **kwargs)
|
'- main(maximum_value=42, path_to_data="path/to/file")
The local runner
In addition to the schedulers that myqueue support, perqueue can also run tasks as background processes, which are run on the local system (the login-node on clusters) on a single core. This ensures that fast pieces of code can be run without having to reserve a job with the scheduler. To stay good friends with your system administrator, this runner should only be used for tasks that take less than a minute or two.
In future releases, there will be a hard limit on the runtime of a local task.
IMPORTANT: In the current releases, the local runner should only be used in the beginning of a workflow, due to how they are run. So, if you have already started submitting things to compute nodes, stop using the local runner.
To submit a task to the local runner, specify the resources as "local:2m", i.e., you specify the partition as local.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file perqueue-0.3.2.tar.gz.
File metadata
- Download URL: perqueue-0.3.2.tar.gz
- Upload date:
- Size: 100.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f68cee99de281f1695fb9b183782a7545fd3e642c7f790c81b4142620e6692d5
|
|
| MD5 |
0aad3a8f567a88d73b299ef43daf126d
|
|
| BLAKE2b-256 |
5e3f171ecabf1c244e9453a9b492a187e5c9f90a11db74d43ef1524cccc90e0e
|
File details
Details for the file perqueue-0.3.2-py3-none-any.whl.
File metadata
- Download URL: perqueue-0.3.2-py3-none-any.whl
- Upload date:
- Size: 85.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0f0a557eba47e85755ca2e48a9088497f8396e25fa6704f9be57716a264cfb94
|
|
| MD5 |
9a1d09673ac9dae7b01687a6521dbb18
|
|
| BLAKE2b-256 |
967016b011395bc59702222540827b4a2ccd83b7643a1c7384c4ced6a00124bb
|