Drivers#
QC Lab comes equipped with three dynamics drivers. These are functions that take a simulation object (see Simulations) as input and carry out the dynamics by executing the recipes of the algorithm object (see Algorithms) associated with the simulation. The three drivers are:
serial_driver
: a serial driver that runs the simulation on a single CPU core,multiprocessing_driver
: a parallel driver that uses Python’s built-inmultiprocessing
module to run the simulation on multiple CPU cores,mpi_driver
: a parallel driver that uses thempi4py
package to run the simulation on multiple CPU cores, possibly across multiple nodes.
Each driver is responsible for managing the execution of the simulation, including dividing the total number of trajectories into batches (if necessary), distributing the batches across available CPU cores, and collecting the results into a single output data object.
All drivers in QC Lab accept the following input arguments (parallel drivers accept an additional argument, see below):
sim
: an instance of theqclab.Simulation
class containing the model, algorithm, and settings for the simulation,seeds
: an optional array of integers specifying the random seeds for each trajectory inthe simulation. If not provided, the seeds will be generated automatically.
data
: an input data object into which the results of the simulation will be added. If not provided, a new data object will be created.
Generically, a driver is called as:
data = driver(sim)
Serial Driver#
The serial driver runs batches of trajectories sequentially without without requesting a particular set of resources. This means it may use multiple CPU cores if available, but it does not attempt to manage or limit the number of CPU cores used. The serial driver is suitable for running small simulations where parallelization is not necessary, or for debugging purposes.
- qclab.dynamics.serial_driver(sim, seeds=None, data=None)#
Serial driver for the dynamics core.
Args
- sim: Simulation
The simulation object containing the model, algorithm, initial state, and settings.
- seeds: ndarray, optional
An array of integer seeds for the trajectories. If None, seeds will be generated automatically.
- data: Data, optional
A Data object for collecting output data. If None, a new Data object will be created.
Returns
- data: Data
The updated Data object containing collected output data.
Parallel Drivers#
The parallel drivers use multiple CPU cores to run batches of trajectories concurrently. This can significantly speed up the simulation, especially for large numbers of trajectories. It is important to recognize that the sim.settings.batch_size
now refers to the number of trajectories that will run on a single CPU core at a time. If you have N
CPU cores available and a batch size of B
, then up to N*B
trajectories will be simulated concurrently. Having a sim.settings.num_trajs = (N+1)*B
will have an unecessary overhead since the last B
trajectories will not be able to run concurrently. For that reason it is recommended to set sim.settings.num_trajs
to be a multiple of N*B
.
In addition to the arguments described above, the parallel drivers accept ntasks
, an integer specifying the number of parallel tasks to use. If ntasks
is not provided, the parallel drivers will attempt to use each available CPU core as a separate task.
- qclab.dynamics.parallel_driver_multiprocessing(sim, seeds=None, data=None, num_tasks=None)#
Parallel driver for the dynamics core using the python library multiprocessing.
Args
- sim: Simulation
The simulation object containing the model, algorithm, initial state, and settings.
- seeds: ndarray, optional
An array of integer seeds for the trajectories. If None, seeds will be generated automatically.
- data: Data, optional
A Data object for collecting output data. If None, a new Data object will be created.
- num_tasks: int, optional
The number of tasks to use for parallel processing. If None, the number of available tasks will be used.
Returns
- data: Data
The updated Data object containing collected output data.
- qclab.dynamics.parallel_driver_mpi(sim, seeds=None, data=None, num_tasks=None)#
Parallel driver for the dynamics core using the mpi4py library.
Args
- sim: Simulation
The simulation object containing the model, algorithm, initial state, and settings.
- seeds: ndarray, optional
An array of integer seeds for the trajectories. If None, seeds will be generated automatically.
- data: Data, optional
A Data object for collecting output data. If None, a new Data object will be created.
- num_tasks: int, optional
The number of tasks to use for parallel processing. If None, the number of available tasks will be used.
Returns
- data: Data
The updated Data object containing collected output data.
The MPI driver requires the mpi4py
package to be installed and an MPI execution environment to run. It is suitable for running large simulations on high-performance computing clusters, and can be invoked using the mpirun
or mpiexec
command, as in:
mpirun -n 4 python my_simulation_script.py
where -n 4
specifies that the simulation should be run using 4 MPI processes. The mpi driver will automatically distribute the batches of trajectories across the available MPI processes (4 in this case).
An example script that uses the mpi driver can be found in examples/mpi_examples/mpi_example.py
along with a SLURM submission script in the same folder. The full source code of these examples is included here for convenience:
mpi_example.py
1"""
2This is an example of how to use the parallel_driver_mpi function in QC Lab.
3
4This script can either be executed by a scheduler like SLURM or can be called in
5terminal by running
6
7mpirun -n num_tasks python mpi_example.py
8
9where num_tasks is the number of tasks you want to run in parallel.
10
11In this example num_tasks is determined automatically by the mpi driver.
12"""
13
14import numpy as np
15import matplotlib.pyplot as plt
16from mpi4py import MPI
17from qclab import Simulation
18from qclab.models import SpinBoson
19from qclab.algorithms import MeanField
20from qclab.dynamics import parallel_driver_mpi
21
22# instantiate a simulation
23sim = Simulation()
24
25# change settings to customize simulation
26sim.settings.num_trajs = 400
27sim.settings.batch_size = 100
28sim.settings.tmax = 10
29sim.settings.dt_update = 0.001
30
31# instantiate a model
32sim.model = SpinBoson()
33# instantiate an algorithm
34sim.algorithm = MeanField()
35# define an initial diabatic wavefunction
36sim.initial_state.wf_db = np.array([1, 0], dtype=complex)
37
38data = parallel_driver_mpi(sim)
39
40
41comm = MPI.COMM_WORLD
42rank = comm.Get_rank()
43if rank == 0:
44 print(data.data_dict["seed"])
qsubmit.txt
1#!/bin/bash
2#SBATCH -A b1143
3#SBATCH -p b1143
4#SBATCH -N 2
5#SBATCH --ntasks-per-node 50
6#SBATCH --cpus-per-task 1
7#SBATCH -t 01:00:00
8#SBATCH --mem-per-cpu=1G
9
10
11mpirun -n 100 python mpi_example.py
Dynamics Core#
- qclab.dynamics.run_dynamics(sim, state, parameters, data)#
Dynamics core for QC Lab.
Args
- sim: Simulation
The simulation object containing the model, algorithm, and settings.
- state: Variable
The state variable object containing the simulation seeds.
- parameters: Variable
The parameters variable object containing any additional parameters.
- data: Data
The data object for collecting output data.
Returns
- data: Data
The updated data object containing collected output data.