libEnsemble is a complete Python toolkit for steering dynamic ensembles of calculations. Workflows are highly portable and detect/integrate heterogeneous resources with little effort. For instance, libEnsemble can automatically detect, assign, and reassign allocated processors and GPUs to ensemble members.

Users select or supply generator and simulator functions to express their ensembles; the generator typically steers the ensemble based on prior simulator results. Such functions can also launch and monitor external executables at any scale.


Begin by loading the python module:

$ module load cray-python

libEnsemble is available on PyPI, conda-forge, the xSDK, and E4S. Most users install libEnsemble via pip:

$ pip install libensemble

Installing libEnsemble in a virtual environment is highly recommended. See the Python on OCLF Systems page for more information.


For a very simple example of using libEsemble see this Simple Tutorial on libEnsemble’s documentation.

For an example that runs a small ensemble with an application that offloads work to a GPU, see this GPU App Tutorial.

Additional information on compiling/running the above sample GPU app is available here.

See this video for an example dynamic-resources workflow on Frontier.

Example Code

 1import numpy as np
 3from libensemble import Ensemble
 4from libensemble.gen_funcs.sampling import uniform_random_sample
 5from libensemble.sim_funcs.six_hump_camel import six_hump_camel
 6from libensemble.specs import ExitCriteria, GenSpecs, SimSpecs
 7from import add_unique_random_streams
 9if __name__ == "__main__":
11    sampling = Ensemble(parse_args=True)
12    sampling.sim_specs = SimSpecs(
13        sim_f=six_hump_camel,
14        inputs=["x"],
15        outputs=[("f", float)],
16    )
18    sampling.gen_specs = GenSpecs(
19        gen_f=uniform_random_sample,
20        outputs=[("x", float, (2,))],
21        user={
22            "gen_batch_size": 500,
23            "lb": np.array([-3, -2]),
24            "ub": np.array([3, 2]),
25        },
26    )
28    sampling.persis_info = add_unique_random_streams({}, sampling.nworkers + 1)
29    sampling.exit_criteria = ExitCriteria(sim_max=101)
31    sampling.save_output(__file__)
33    if sampling.is_manager:
34        print("Some output data:\n", sampling.H[["x", "f"]][:10])

Job Submission

Upon initialization, libEnsemble will detect available nodes and GPUs from the Slurm environment, and allocate those resources towards application-launches.

Start an interactive session:

$ salloc --nodes=2 -A <project_id> --time=00:10:00

Within the session (multiprocessing comms, all processes on first node):

$ python --comms local --nworkers 9