parallel_task.txt
99 lines
| 4.1 KiB
| text/plain
|
TextLexer
Brian E Granger
|
r1256 | .. _paralleltask: | ||
Brian Granger
|
r1678 | ========================== | ||
The IPython task interface | ||||
========================== | ||||
Brian E Granger
|
r1256 | |||
Brian Granger
|
r1678 | The task interface to the controller presents the engines as a fault tolerant, dynamic load-balanced system or workers. Unlike the multiengine interface, in the task interface, the user have no direct access to individual engines. In some ways, this interface is simpler, but in other ways it is more powerful. | ||
Best of all the user can use both of these interfaces running at the same time to take advantage or both of their strengths. When the user can break up the user's work into segments that do not depend on previous execution, the task interface is ideal. But it also has more power and flexibility, allowing the user to guide the distribution of jobs, without having to assign tasks to engines explicitly. | ||||
Brian E Granger
|
r1256 | |||
Starting the IPython controller and engines | ||||
=========================================== | ||||
Brian Granger
|
r1678 | To follow along with this tutorial, you will need to start the IPython | ||
controller and four IPython engines. The simplest way of doing this is to use | ||||
the :command:`ipcluster` command:: | ||||
Brian E Granger
|
r1256 | |||
Brian Granger
|
r1788 | $ ipcluster local -n 4 | ||
Brian E Granger
|
r1256 | |||
Brian Granger
|
r1678 | For more detailed information about starting the controller and engines, see | ||
our :ref:`introduction <ip1par>` to using IPython for parallel computing. | ||||
Creating a ``TaskClient`` instance | ||||
========================================= | ||||
The first step is to import the IPython :mod:`IPython.kernel.client` module | ||||
Brian Granger
|
r1788 | and then create a :class:`TaskClient` instance: | ||
.. sourcecode:: ipython | ||||
Brian Granger
|
r1678 | |||
In [1]: from IPython.kernel import client | ||||
In [2]: tc = client.TaskClient() | ||||
This form assumes that the :file:`ipcontroller-tc.furl` is in the | ||||
:file:`~./ipython/security` directory on the client's host. If not, the | ||||
Brian Granger
|
r1788 | location of the FURL file must be given as an argument to the | ||
constructor: | ||||
.. sourcecode:: ipython | ||||
Brian Granger
|
r1678 | |||
Brian Granger
|
r1788 | In [2]: mec = client.TaskClient('/path/to/my/ipcontroller-tc.furl') | ||
Brian Granger
|
r1678 | |||
Quick and easy parallelism | ||||
========================== | ||||
In many cases, you simply want to apply a Python function to a sequence of objects, but *in parallel*. Like the multiengine interface, the task interface provides two simple ways of accomplishing this: a parallel version of :func:`map` and ``@parallel`` function decorator. However, the verions in the task interface have one important difference: they are dynamically load balanced. Thus, if the execution time per item varies significantly, you should use the versions in the task interface. | ||||
Parallel map | ||||
------------ | ||||
Brian Granger
|
r1788 | The parallel :meth:`map` in the task interface is similar to that in the multiengine interface: | ||
.. sourcecode:: ipython | ||||
Brian Granger
|
r1678 | |||
In [63]: serial_result = map(lambda x:x**10, range(32)) | ||||
In [64]: parallel_result = tc.map(lambda x:x**10, range(32)) | ||||
In [65]: serial_result==parallel_result | ||||
Out[65]: True | ||||
Parallel function decorator | ||||
--------------------------- | ||||
Brian Granger
|
r1788 | Parallel functions are just like normal function, but they can be called on sequences and *in parallel*. The multiengine interface provides a decorator that turns any Python function into a parallel function: | ||
.. sourcecode:: ipython | ||||
Brian E Granger
|
r1256 | |||
Brian Granger
|
r1678 | In [10]: @tc.parallel() | ||
....: def f(x): | ||||
....: return 10.0*x**4 | ||||
....: | ||||
Brian E Granger
|
r1256 | |||
Brian Granger
|
r1678 | In [11]: f(range(32)) # this is done in parallel | ||
Out[11]: | ||||
[0.0,10.0,160.0,...] | ||||
Brian E Granger
|
r1256 | |||
Brian Granger
|
r1678 | More details | ||
============ | ||||
Brian E Granger
|
r1256 | |||
Brian Granger
|
r1678 | The :class:`TaskClient` has many more powerful features that allow quite a bit of flexibility in how tasks are defined and run. The next places to look are in the following classes: | ||
Brian E Granger
|
r1256 | |||
Brian Granger
|
r1678 | * :class:`IPython.kernel.client.TaskClient` | ||
* :class:`IPython.kernel.client.StringTask` | ||||
* :class:`IPython.kernel.client.MapTask` | ||||
Brian E Granger
|
r1256 | |||
Brian Granger
|
r1678 | The following is an overview of how to use these classes together: | ||
Brian E Granger
|
r1256 | |||
Brian Granger
|
r1678 | 1. Create a :class:`TaskClient`. | ||
2. Create one or more instances of :class:`StringTask` or :class:`MapTask` | ||||
to define your tasks. | ||||
3. Submit your tasks to using the :meth:`run` method of your | ||||
:class:`TaskClient` instance. | ||||
4. Use :meth:`TaskClient.get_task_result` to get the results of the | ||||
tasks. | ||||
Brian E Granger
|
r1256 | |||
Brian Granger
|
r1678 | We are in the process of developing more detailed information about the task interface. For now, the docstrings of the :class:`TaskClient`, :class:`StringTask` and :class:`MapTask` classes should be consulted. | ||
Brian E Granger
|
r1256 | |||