4.7: Parallelism: Using the Joblib backend
This example demonstrates how to use the Joblib backend for
simulating dipoles using hnn_core
.
hnn_core
can take advantage of the Joblib library
to run multiple independent simulations simultaneously
across multiple CPU processors. This is an example of
"embarrassingly
parallel" processing jobs. In HNN, this is commonly done if you want
to run many "trials" of the same simulation. Since each trial simulation
is fully independent of the other trial simulations, each trial
simulation can be run on its own CPU core. Joblib parallelism is
particularly useful if you are using batch
simulation to explore parameter spaces.
Note that to use Joblib parallelism, you need either the
conda
install or the Joblib Installation
dependencies described in
our Installation Guide here.
Note that Joblib parallelism is distinct from hnn_core
's
use of MPI
parallelism, which can be found here.
# Authors: Mainak Jas
# Blake Caldwell
# Austin Soplata
Let us import what we need from hnn_core
:
import matplotlib.pyplot as plt
from hnn_core import simulate_dipole, jones_2009_model
from hnn_core.viz import plot_dipole
Following our Alpha
example, we will create our network and add a ~10 Hz "bursty"
drive:
net = jones_2009_model()
weights_ampa = {'L2_pyramidal': 5.4e-5, 'L5_pyramidal': 5.4e-5}
net.add_bursty_drive(
'bursty', tstart=50., burst_rate=10, burst_std=20., numspikes=2,
spike_isi=10, n_drive_cells=10, location='distal',
weights_ampa=weights_ampa, event_seed=278)
Finally, we will simulate using the JoblibBackend
class. You can control the number of CPU cores to use via
n_jobs
, while the number of total trials to be run can be
specified by n_trials
. Note that these numbers do NOT have
to match: you can ask for more trials than there are jobs available, and
Joblib will simply execute later jobs after the first batch has
completed.
from hnn_core import JoblibBackend
with JoblibBackend(n_jobs=4):
dpls = simulate_dipole(net, tstop=210., n_trials=6)
Out:
Joblib will run 6 trial(s) in parallel by distributing trials over 4 jobs.
Building the NEURON model
Building the NEURON model
Loading custom mechanism files from /opt/anaconda3/envs/website-redesign-mpi/lib/python3.12/site-packages/hnn_core/mod/arm64/.libs/libnrnmech.so
Building the NEURON model
Loading custom mechanism files from /opt/anaconda3/envs/website-redesign-mpi/lib/python3.12/site-packages/hnn_core/mod/arm64/.libs/libnrnmech.so
Building the NEURON model
[Done]
Trial 2: 0.03 ms...
[Done]
Trial 4: 0.03 ms...
[Done]
[Done]
Trial 3: 0.03 ms...
Trial 1: 0.03 ms...
Trial 2: 10.0 ms...
Trial 4: 10.0 ms...
Trial 1: 10.0 ms...
Trial 3: 10.0 ms...
Trial 2: 20.0 ms...
Trial 4: 20.0 ms...
Trial 3: 20.0 ms...
Trial 1: 20.0 ms...
Trial 2: 30.0 ms...
Trial 4: 30.0 ms...
Trial 3: 30.0 ms...
Trial 1: 30.0 ms...
Trial 2: 40.0 ms...
Trial 4: 40.0 ms...
Trial 3: 40.0 ms...
Trial 1: 40.0 ms...
Trial 2: 50.0 ms...
Trial 4: 50.0 ms...
Trial 3: 50.0 ms...
Trial 1: 50.0 ms...
Trial 2: 60.0 ms...
Trial 4: 60.0 ms...
Trial 3: 60.0 ms...
Trial 1: 60.0 ms...
Trial 2: 70.0 ms...
Trial 4: 70.0 ms...
Trial 3: 70.0 ms...
Trial 1: 70.0 ms...
Trial 2: 80.0 ms...
Trial 4: 80.0 ms...
Trial 3: 80.0 ms...
Trial 1: 80.0 ms...
Trial 2: 90.0 ms...
Trial 4: 90.0 ms...
Trial 3: 90.0 ms...
Trial 1: 90.0 ms...
Trial 2: 100.0 ms...
Trial 4: 100.0 ms...
Trial 3: 100.0 ms...
Trial 1: 100.0 ms...
Trial 2: 110.0 ms...
Trial 4: 110.0 ms...
Trial 3: 110.0 ms...
Trial 1: 110.0 ms...
Trial 2: 120.0 ms...
Trial 4: 120.0 ms...
Trial 3: 120.0 ms...
Trial 1: 120.0 ms...
Trial 2: 130.0 ms...
Trial 4: 130.0 ms...
Trial 3: 130.0 ms...
Trial 1: 130.0 ms...
Trial 4: 140.0 ms...
Trial 2: 140.0 ms...
Trial 3: 140.0 ms...
Trial 1: 140.0 ms...
Trial 4: 150.0 ms...
Trial 2: 150.0 ms...
Trial 3: 150.0 ms...
Trial 1: 150.0 ms...
Trial 2: 160.0 ms...
Trial 4: 160.0 ms...
Trial 3: 160.0 ms...
Trial 1: 160.0 ms...
Trial 4: 170.0 ms...
Trial 2: 170.0 ms...
Trial 3: 170.0 ms...
Trial 1: 170.0 ms...
Trial 4: 180.0 ms...
Trial 2: 180.0 ms...
Trial 3: 180.0 ms...
Trial 1: 180.0 ms...
Trial 4: 190.0 ms...
Trial 2: 190.0 ms...
Trial 3: 190.0 ms...
Trial 1: 190.0 ms...
Trial 4: 200.0 ms...
Trial 2: 200.0 ms...
Trial 3: 200.0 ms...
Trial 1: 200.0 ms...
Building the NEURON model
Building the NEURON model
[Done]
[Done]
Trial 6: 0.03 ms...
Trial 5: 0.03 ms...
Trial 6: 10.0 ms...
Trial 5: 10.0 ms...
Trial 6: 20.0 ms...
Trial 5: 20.0 ms...
Trial 6: 30.0 ms...
Trial 5: 30.0 ms...
Trial 6: 40.0 ms...
Trial 5: 40.0 ms...
Trial 6: 50.0 ms...
Trial 5: 50.0 ms...
Trial 6: 60.0 ms...
Trial 5: 60.0 ms...
Trial 6: 70.0 ms...
Trial 5: 70.0 ms...
Trial 6: 80.0 ms...
Trial 5: 80.0 ms...
Trial 6: 90.0 ms...
Trial 5: 90.0 ms...
Trial 6: 100.0 ms...
Trial 5: 100.0 ms...
Trial 6: 110.0 ms...
Trial 5: 110.0 ms...
Trial 6: 120.0 ms...
Trial 5: 120.0 ms...
Trial 6: 130.0 ms...
Trial 5: 130.0 ms...
Trial 6: 140.0 ms...
Trial 5: 140.0 ms...
Trial 6: 150.0 ms...
Trial 5: 150.0 ms...
Trial 6: 160.0 ms...
Trial 5: 160.0 ms...
Trial 6: 170.0 ms...
Trial 5: 170.0 ms...
Trial 6: 180.0 ms...
Trial 5: 180.0 ms...
Trial 6: 190.0 ms...
Trial 5: 190.0 ms...
Trial 6: 200.0 ms...
Trial 5: 200.0 ms...
plot_dipole(dpls, show=False)
plt.show()
Out:
<Figure size 640x480 with 1 Axes>