Parallel Execution of Models¶
Introduction¶
QInfer provides tools to expedite simulation by distributing computation across multiple nodes using standard parallelization tools.
Distributed Computation with IPython¶
The ipyparallel package (previously IPython.parallel
) provides
facilities for parallelizing computation across multiple cores and/or nodes.
ipyparallel separates computation into a controller that is responsible
for one or more engines, and a client that sends commands to these engines
via the controller. QInfer can use a client to send likelihood evaluation
calls to engines, via the DirectViewParallelizedModel
class.
This class takes a DirectView
onto one
or more engines, typically obtained with an expression similar to
client[:]
, and splits calls to likelihood()
across the engines accessible from the DirectView
.
Note
QInfer does not include ipyparallel in its installation, so you must install it separately. To run the example code also requires some initialization, which is also described in the docs.
>>> from ipyparallel import Client
>>> from qinfer import SimplePrecessionModel
>>> from qinfer import DirectViewParallelizedModel
>>> c = Client()
>>> serial_model = SimplePrecessionModel()
>>> parallel_model = DirectViewParallelizedModel(serial_model, c[:])
The newly decorated model will now distribute likelihood calls, such that each engine computes the likelihood for an equal number of particles. As a consequence, information shared per-experiment or per-outcome is local to each engine, and is not distributed. Therefore, this approach works best at quickly parallelizing where the per-model cost is significantly larger than the per-experiment or per-outcome cost.
Note
The DirectViewParallelizedModel
assumes that it has ownership
over engines, such that the behavior is unpredictable if any further
commands are sent to the engines from outside the class.
Distributed Performance Testing¶
As an alternative to distributing a single likelihood call across multiple
engines, QInfer also supports distributed Performance and Robustness Testing. Under this
model, each engine performs an independent trial of an estimation procedure,
which is then collected by the client process. Distributed performance testing
is implemented using the perf_test_multiple()
function, with the
keyword argument apply
provided. For instance, the ipyparallel package
offers a LoadBalancedView
class whose
apply()
method sends tasks to engines
according to their respective loads.
>>> lbview = client.load_balanced_view()
>>> performance = qi.perf_test_multiple(
... 100, serial_model, 6000, prior, 200, heuristic_class,
... apply=lbview.apply
... )
Examples of both approaches to parallelization are provided as a Jupyter Notebook.
GPGPU-based Likelihood Computation with PyOpenCL¶
Though QInfer does not yet have built-in support for GPU-based parallelization, PyOpenCL can be used to effectively distribute models as well. Here, the Cartesian product over outcomes, models and experiments matches closely the OpenCL concept of a global ID, as this example demonstrates. Once a kernel is developed in this way, PyOpenCL will allow for it to be used with any available OpenCL-compliant device.
Note that for sufficiently fast models, the overhead of copying data between the CPU and GPU may overwhelm any speed benefits obtained by this parallelization.