|
| 1 | +.. _parallel_process: |
| 2 | + |
| 3 | +========================= |
| 4 | +How to Parallelise Trials |
| 5 | +========================= |
| 6 | + |
| 7 | +It is possible to repeat a simulation in parallel using the cores available on a |
| 8 | +given computer. This can lead to decreases in computational time as instead of |
| 9 | +running each successive simulation :ref:`one after the other <tutorial-iv>` they |
| 10 | +can be run at the same time. |
| 11 | + |
| 12 | +As an example consider the following simulation network:: |
| 13 | + |
| 14 | + >>> import ciw |
| 15 | + >>> N = ciw.create_network(arrival_distributions=[ciw.dists.Exponential(rate=0.2)], |
| 16 | + ... service_distributions=[ciw.dists.Exponential(rate=0.1)], |
| 17 | + ... number_of_servers=[3]) |
| 18 | + |
| 19 | +The following function will return the mean wait time:: |
| 20 | + |
| 21 | + >>> def get_mean_wait(network, seed=0, max_time=10000): |
| 22 | + ... """Return the mean waiting time for a given network""" |
| 23 | + ... ciw.seed(seed) |
| 24 | + ... Q = ciw.Simulation(N) |
| 25 | + ... Q.simulate_until_max_time(max_simulation_time=max_time) |
| 26 | + ... recs = Q.get_all_records() |
| 27 | + ... waits = [r.waiting_time for r in recs] |
| 28 | + ... mean_wait = sum(waits) / len(waits) |
| 29 | + ... return mean_wait |
| 30 | + >>> get_mean_wait(network=N) |
| 31 | + 3.386690... |
| 32 | + |
| 33 | +To be able to better approximate the average wait, the above function will be |
| 34 | +repeated and the average taken:: |
| 35 | + |
| 36 | + >>> import numpy as np |
| 37 | + >>> max_time = 500 |
| 38 | + >>> repetitions = 200 |
| 39 | + >>> np.mean([run_simulation(network=N, max_time=max_time, seed=seed) for seed in range(repetitions)]) |
| 40 | + 3.762233... |
| 41 | + |
| 42 | +To obtain the above by running 2 simulations at the same time (assuming that 2 |
| 43 | +cores are available), the :code:`multiprocessing` library can be used. In which |
| 44 | +case the following :download:`main.py |
| 45 | +<../_static/script_for_parallel_processing/main.py>` script gives a working |
| 46 | +example: |
| 47 | + |
| 48 | +.. literalinclude:: ../_static/script_for_parallel_processing/main.py |
| 49 | + |
| 50 | +It is possible to use :code:`multiprocessing.cpu_count()` to obtain the number |
| 51 | +of available cores. |
| 52 | + |
| 53 | +Note that the conditional :code:`if __name__ == '__main__':` is needed to ensure |
| 54 | +that :code:`get_mean_wait` can be pickled. This is necessary to ensure that it |
| 55 | +can be used by the parallel processing pool. |
| 56 | + |
| 57 | +The :code:`multiprocessing` library is part of the python standard library so no |
| 58 | +further dependencies are required. However other options are available, one |
| 59 | +example of which is `dask <https://www.dask.org>`_. |
0 commit comments