Skip to main content

Scale serial and MPI-parallel python functions over hundreds of compute nodes all from within a jupyter notebook or serial python process.

Project description

executorlib

Unittests Coverage Status Binder

Up-scale python functions for high performance computing (HPC) with executorlib.

Key Features

  • Up-scale your Python functions beyond a single computer. - executorlib extends the Executor interface from the Python standard library and combines it with job schedulers for high performance computing (HPC) including the Simple Linux Utility for Resource Management (SLURM) and flux. With this combination executorlib allows users to distribute their Python functions over multiple compute nodes.
  • Parallelize your Python program one function at a time - executorlib allows users to assign dedicated computing resources like CPU cores, threads or GPUs to one Python function call at a time. So you can accelerate your Python code function by function.
  • Permanent caching of intermediate results to accelerate rapid prototyping - To accelerate the development of machine learning pipelines and simulation workflows executorlib provides optional caching of intermediate results for iterative development in interactive environments like jupyter notebooks.

Examples

The Python standard library provides the Executor interface with the ProcessPoolExecutor and the ThreadPoolExecutor for parallel execution of Python functions on a single computer. executorlib extends this functionality to distribute Python functions over multiple computers within a high performance computing (HPC) cluster. This can be either achieved by submitting each function as individual job to the HPC job scheduler - HPC Submission Mode - or by requesting a compute allocation of multiple nodes and then distribute the Python functions within this - allocation - HPC Allocation Mode. Finally, to accelerate the development process executorlib also provides a - Local Mode - to use the executorlib functionality on a single workstation for testing. Starting with the Local Mode set by setting the backend parameter to local - backend="local":

from executorlib import Executor


with Executor(backend="local") as exe:
    future_lst = [exe.submit(sum, [i, i]) for i in range(1, 5)]
    print([f.result() for f in future_lst])

In the same way executorlib can also execute Python functions which use additional computing resources, like multiple CPU cores, CPU threads or GPUs. For example if the Python function internally uses the Message Passing Interface (MPI) via the mpi4py Python libary:

from executorlib import Executor


def calc(i):
    from mpi4py import MPI

    size = MPI.COMM_WORLD.Get_size()
    rank = MPI.COMM_WORLD.Get_rank()
    return i, size, rank


with Executor(backend="local") as exe:
    fs = exe.submit(calc, 3, resource_dict={"cores": 2})
    print(fs.result())

The additional resource_dict parameter defines the computing resources allocated to the execution of the submitted Python function. In addition to the compute cores cores, the resource dictionary can also define the threads per core as threads_per_core, the GPUs per core as gpus_per_core, the working directory with cwd, the option to use the OpenMPI oversubscribe feature with openmpi_oversubscribe and finally for the Simple Linux Utility for Resource Management (SLURM) queuing system the option to provide additional command line arguments with the slurm_cmd_args parameter - [resource dictionary](https://executorlib.readthedocs.io/en/latest/trouble_shooting.html#resource-dictionary This flexibility to assign computing resources on a per-function-call basis simplifies the up-scaling of Python programs. Only the part of the Python functions which benefit from parallel execution are implemented as MPI parallel Python funtions, while the rest of the program remains serial.

The same function can be submitted to the SLURM queuing by just changing the backend parameter to slurm_submission. The rest of the example remains the same, which highlights how executorlib accelerates the rapid prototyping and up-scaling of HPC Python programs.

from executorlib import Executor


def calc(i):
    from mpi4py import MPI

    size = MPI.COMM_WORLD.Get_size()
    rank = MPI.COMM_WORLD.Get_rank()
    return i, size, rank


with Executor(backend="slurm_submission") as exe:
    fs = exe.submit(calc, 3, resource_dict={"cores": 2})
    print(fs.result())

In this case the Python simple queuing system adapter (pysqa) is used to submit the calc() function to the SLURM job scheduler and request an allocation with two CPU cores for the execution of the function - HPC Submission Mode. In the background the sbatch command is used to request the allocation to execute the Python function.

Within a given SLURM allocation executorlib can also be used to assign a subset of the available computing resources to execute a given Python function. In terms of the SLURM commands, this functionality internally uses the srun command to receive a subset of the resources of a given queuing system allocation.

from executorlib import Executor


def calc(i):
    from mpi4py import MPI

    size = MPI.COMM_WORLD.Get_size()
    rank = MPI.COMM_WORLD.Get_rank()
    return i, size, rank


with Executor(backend="slurm_allocation") as exe:
    fs = exe.submit(calc, 3, resource_dict={"cores": 2})
    print(fs.result())

In addition, to support for SLURM executorlib also provides support for the hierarchical flux job scheduler. The flux job scheduler is developed at Larwence Livermore National Laboratory to address the needs for the up-coming generation of Exascale computers. Still even on traditional HPC clusters the hierarchical approach of the flux is beneficial to distribute hundreds of tasks within a given allocation. Even when SLURM is used as primary job scheduler of your HPC, it is recommended to use SLURM with flux as hierarchical job scheduler within the allocations.

Documentation

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

executorlib-0.0.5.tar.gz (49.6 kB view details)

Uploaded Source

Built Distribution

executorlib-0.0.5-py3-none-any.whl (52.0 kB view details)

Uploaded Python 3

File details

Details for the file executorlib-0.0.5.tar.gz.

File metadata

  • Download URL: executorlib-0.0.5.tar.gz
  • Upload date:
  • Size: 49.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.7

File hashes

Hashes for executorlib-0.0.5.tar.gz
Algorithm Hash digest
SHA256 1a9efd09e10d8e25c11f5fe65e6f073b4700b0f53d31ec11b1338e42cc3a5250
MD5 55c2c69c6a162cd2a8ba585d4aaf3b02
BLAKE2b-256 6af54625300db184b7b18aa6b5d5fd936af36ee5dc5de8e2f5fe5e629e744b74

See more details on using hashes here.

Provenance

The following attestation bundles were made for executorlib-0.0.5.tar.gz:

Publisher: deploy.yml on pyiron/executorlib

Attestations:

File details

Details for the file executorlib-0.0.5-py3-none-any.whl.

File metadata

  • Download URL: executorlib-0.0.5-py3-none-any.whl
  • Upload date:
  • Size: 52.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.7

File hashes

Hashes for executorlib-0.0.5-py3-none-any.whl
Algorithm Hash digest
SHA256 2acaa1902ab8567ccd75d0a0858dc5067d84ea6ed7dd29b4c34f3e3d5bf26474
MD5 7790ed3479fdc26f36bb12cb1cc5058c
BLAKE2b-256 ab4314f59cde49bb314021b4b87dd3ddf75557a31a874bf8d5302232aa205a7e

See more details on using hashes here.

Provenance

The following attestation bundles were made for executorlib-0.0.5-py3-none-any.whl:

Publisher: deploy.yml on pyiron/executorlib

Attestations:

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page