##// END OF EJS Templates
document promoting an Engine to a regular Kernel
MinRK -
Show More
@@ -1,944 +1,1002 b''
1 .. _parallel_multiengine:
1 .. _parallel_multiengine:
2
2
3 ==========================
3 ==========================
4 IPython's Direct interface
4 IPython's Direct interface
5 ==========================
5 ==========================
6
6
7 The direct, or multiengine, interface represents one possible way of working with a set of
7 The direct, or multiengine, interface represents one possible way of working with a set of
8 IPython engines. The basic idea behind the multiengine interface is that the
8 IPython engines. The basic idea behind the multiengine interface is that the
9 capabilities of each engine are directly and explicitly exposed to the user.
9 capabilities of each engine are directly and explicitly exposed to the user.
10 Thus, in the multiengine interface, each engine is given an id that is used to
10 Thus, in the multiengine interface, each engine is given an id that is used to
11 identify the engine and give it work to do. This interface is very intuitive
11 identify the engine and give it work to do. This interface is very intuitive
12 and is designed with interactive usage in mind, and is the best place for
12 and is designed with interactive usage in mind, and is the best place for
13 new users of IPython to begin.
13 new users of IPython to begin.
14
14
15 Starting the IPython controller and engines
15 Starting the IPython controller and engines
16 ===========================================
16 ===========================================
17
17
18 To follow along with this tutorial, you will need to start the IPython
18 To follow along with this tutorial, you will need to start the IPython
19 controller and four IPython engines. The simplest way of doing this is to use
19 controller and four IPython engines. The simplest way of doing this is to use
20 the :command:`ipcluster` command::
20 the :command:`ipcluster` command::
21
21
22 $ ipcluster start -n 4
22 $ ipcluster start -n 4
23
23
24 For more detailed information about starting the controller and engines, see
24 For more detailed information about starting the controller and engines, see
25 our :ref:`introduction <parallel_overview>` to using IPython for parallel computing.
25 our :ref:`introduction <parallel_overview>` to using IPython for parallel computing.
26
26
27 Creating a ``DirectView`` instance
27 Creating a ``DirectView`` instance
28 ==================================
28 ==================================
29
29
30 The first step is to import the IPython :mod:`IPython.parallel`
30 The first step is to import the IPython :mod:`IPython.parallel`
31 module and then create a :class:`.Client` instance:
31 module and then create a :class:`.Client` instance:
32
32
33 .. sourcecode:: ipython
33 .. sourcecode:: ipython
34
34
35 In [1]: from IPython.parallel import Client
35 In [1]: from IPython.parallel import Client
36
36
37 In [2]: rc = Client()
37 In [2]: rc = Client()
38
38
39 This form assumes that the default connection information (stored in
39 This form assumes that the default connection information (stored in
40 :file:`ipcontroller-client.json` found in :file:`IPYTHONDIR/profile_default/security`) is
40 :file:`ipcontroller-client.json` found in :file:`IPYTHONDIR/profile_default/security`) is
41 accurate. If the controller was started on a remote machine, you must copy that connection
41 accurate. If the controller was started on a remote machine, you must copy that connection
42 file to the client machine, or enter its contents as arguments to the Client constructor:
42 file to the client machine, or enter its contents as arguments to the Client constructor:
43
43
44 .. sourcecode:: ipython
44 .. sourcecode:: ipython
45
45
46 # If you have copied the json connector file from the controller:
46 # If you have copied the json connector file from the controller:
47 In [2]: rc = Client('/path/to/ipcontroller-client.json')
47 In [2]: rc = Client('/path/to/ipcontroller-client.json')
48 # or to connect with a specific profile you have set up:
48 # or to connect with a specific profile you have set up:
49 In [3]: rc = Client(profile='mpi')
49 In [3]: rc = Client(profile='mpi')
50
50
51
51
52 To make sure there are engines connected to the controller, users can get a list
52 To make sure there are engines connected to the controller, users can get a list
53 of engine ids:
53 of engine ids:
54
54
55 .. sourcecode:: ipython
55 .. sourcecode:: ipython
56
56
57 In [3]: rc.ids
57 In [3]: rc.ids
58 Out[3]: [0, 1, 2, 3]
58 Out[3]: [0, 1, 2, 3]
59
59
60 Here we see that there are four engines ready to do work for us.
60 Here we see that there are four engines ready to do work for us.
61
61
62 For direct execution, we will make use of a :class:`DirectView` object, which can be
62 For direct execution, we will make use of a :class:`DirectView` object, which can be
63 constructed via list-access to the client:
63 constructed via list-access to the client:
64
64
65 .. sourcecode:: ipython
65 .. sourcecode:: ipython
66
66
67 In [4]: dview = rc[:] # use all engines
67 In [4]: dview = rc[:] # use all engines
68
68
69 .. seealso::
69 .. seealso::
70
70
71 For more information, see the in-depth explanation of :ref:`Views <parallel_details>`.
71 For more information, see the in-depth explanation of :ref:`Views <parallel_details>`.
72
72
73
73
74 Quick and easy parallelism
74 Quick and easy parallelism
75 ==========================
75 ==========================
76
76
77 In many cases, you simply want to apply a Python function to a sequence of
77 In many cases, you simply want to apply a Python function to a sequence of
78 objects, but *in parallel*. The client interface provides a simple way
78 objects, but *in parallel*. The client interface provides a simple way
79 of accomplishing this: using the DirectView's :meth:`~DirectView.map` method.
79 of accomplishing this: using the DirectView's :meth:`~DirectView.map` method.
80
80
81 Parallel map
81 Parallel map
82 ------------
82 ------------
83
83
84 Python's builtin :func:`map` functions allows a function to be applied to a
84 Python's builtin :func:`map` functions allows a function to be applied to a
85 sequence element-by-element. This type of code is typically trivial to
85 sequence element-by-element. This type of code is typically trivial to
86 parallelize. In fact, since IPython's interface is all about functions anyway,
86 parallelize. In fact, since IPython's interface is all about functions anyway,
87 you can just use the builtin :func:`map` with a :class:`RemoteFunction`, or a
87 you can just use the builtin :func:`map` with a :class:`RemoteFunction`, or a
88 DirectView's :meth:`map` method:
88 DirectView's :meth:`map` method:
89
89
90 .. sourcecode:: ipython
90 .. sourcecode:: ipython
91
91
92 In [62]: serial_result = map(lambda x:x**10, range(32))
92 In [62]: serial_result = map(lambda x:x**10, range(32))
93
93
94 In [63]: parallel_result = dview.map_sync(lambda x: x**10, range(32))
94 In [63]: parallel_result = dview.map_sync(lambda x: x**10, range(32))
95
95
96 In [67]: serial_result==parallel_result
96 In [67]: serial_result==parallel_result
97 Out[67]: True
97 Out[67]: True
98
98
99
99
100 .. note::
100 .. note::
101
101
102 The :class:`DirectView`'s version of :meth:`map` does
102 The :class:`DirectView`'s version of :meth:`map` does
103 not do dynamic load balancing. For a load balanced version, use a
103 not do dynamic load balancing. For a load balanced version, use a
104 :class:`LoadBalancedView`.
104 :class:`LoadBalancedView`.
105
105
106 .. seealso::
106 .. seealso::
107
107
108 :meth:`map` is implemented via :class:`ParallelFunction`.
108 :meth:`map` is implemented via :class:`ParallelFunction`.
109
109
110 Remote function decorators
110 Remote function decorators
111 --------------------------
111 --------------------------
112
112
113 Remote functions are just like normal functions, but when they are called,
113 Remote functions are just like normal functions, but when they are called,
114 they execute on one or more engines, rather than locally. IPython provides
114 they execute on one or more engines, rather than locally. IPython provides
115 two decorators:
115 two decorators:
116
116
117 .. sourcecode:: ipython
117 .. sourcecode:: ipython
118
118
119 In [10]: @dview.remote(block=True)
119 In [10]: @dview.remote(block=True)
120 ....: def getpid():
120 ....: def getpid():
121 ....: import os
121 ....: import os
122 ....: return os.getpid()
122 ....: return os.getpid()
123 ....:
123 ....:
124
124
125 In [11]: getpid()
125 In [11]: getpid()
126 Out[11]: [12345, 12346, 12347, 12348]
126 Out[11]: [12345, 12346, 12347, 12348]
127
127
128 The ``@parallel`` decorator creates parallel functions, that break up an element-wise
128 The ``@parallel`` decorator creates parallel functions, that break up an element-wise
129 operations and distribute them, reconstructing the result.
129 operations and distribute them, reconstructing the result.
130
130
131 .. sourcecode:: ipython
131 .. sourcecode:: ipython
132
132
133 In [12]: import numpy as np
133 In [12]: import numpy as np
134
134
135 In [13]: A = np.random.random((64,48))
135 In [13]: A = np.random.random((64,48))
136
136
137 In [14]: @dview.parallel(block=True)
137 In [14]: @dview.parallel(block=True)
138 ....: def pmul(A,B):
138 ....: def pmul(A,B):
139 ....: return A*B
139 ....: return A*B
140
140
141 In [15]: C_local = A*A
141 In [15]: C_local = A*A
142
142
143 In [16]: C_remote = pmul(A,A)
143 In [16]: C_remote = pmul(A,A)
144
144
145 In [17]: (C_local == C_remote).all()
145 In [17]: (C_local == C_remote).all()
146 Out[17]: True
146 Out[17]: True
147
147
148 Calling a ``@parallel`` function *does not* correspond to map. It is used for splitting
148 Calling a ``@parallel`` function *does not* correspond to map. It is used for splitting
149 element-wise operations that operate on a sequence or array. For ``map`` behavior,
149 element-wise operations that operate on a sequence or array. For ``map`` behavior,
150 parallel functions do have a map method.
150 parallel functions do have a map method.
151
151
152 ==================== ============================ =============================
152 ==================== ============================ =============================
153 call pfunc(seq) pfunc.map(seq)
153 call pfunc(seq) pfunc.map(seq)
154 ==================== ============================ =============================
154 ==================== ============================ =============================
155 # of tasks # of engines (1 per engine) # of engines (1 per engine)
155 # of tasks # of engines (1 per engine) # of engines (1 per engine)
156 # of remote calls # of engines (1 per engine) ``len(seq)``
156 # of remote calls # of engines (1 per engine) ``len(seq)``
157 argument to remote ``seq[i:j]`` (sub-sequence) ``seq[i]`` (single element)
157 argument to remote ``seq[i:j]`` (sub-sequence) ``seq[i]`` (single element)
158 ==================== ============================ =============================
158 ==================== ============================ =============================
159
159
160 A quick example to illustrate the difference in arguments for the two modes:
160 A quick example to illustrate the difference in arguments for the two modes:
161
161
162 .. sourcecode:: ipython
162 .. sourcecode:: ipython
163
163
164 In [16]: @dview.parallel(block=True)
164 In [16]: @dview.parallel(block=True)
165 ....: def echo(x):
165 ....: def echo(x):
166 ....: return str(x)
166 ....: return str(x)
167 ....:
167 ....:
168
168
169 In [17]: echo(range(5))
169 In [17]: echo(range(5))
170 Out[17]: ['[0, 1]', '[2]', '[3]', '[4]']
170 Out[17]: ['[0, 1]', '[2]', '[3]', '[4]']
171
171
172 In [18]: echo.map(range(5))
172 In [18]: echo.map(range(5))
173 Out[18]: ['0', '1', '2', '3', '4']
173 Out[18]: ['0', '1', '2', '3', '4']
174
174
175
175
176 .. seealso::
176 .. seealso::
177
177
178 See the :func:`~.remotefunction.parallel` and :func:`~.remotefunction.remote`
178 See the :func:`~.remotefunction.parallel` and :func:`~.remotefunction.remote`
179 decorators for options.
179 decorators for options.
180
180
181 Calling Python functions
181 Calling Python functions
182 ========================
182 ========================
183
183
184 The most basic type of operation that can be performed on the engines is to
184 The most basic type of operation that can be performed on the engines is to
185 execute Python code or call Python functions. Executing Python code can be
185 execute Python code or call Python functions. Executing Python code can be
186 done in blocking or non-blocking mode (non-blocking is default) using the
186 done in blocking or non-blocking mode (non-blocking is default) using the
187 :meth:`.View.execute` method, and calling functions can be done via the
187 :meth:`.View.execute` method, and calling functions can be done via the
188 :meth:`.View.apply` method.
188 :meth:`.View.apply` method.
189
189
190 apply
190 apply
191 -----
191 -----
192
192
193 The main method for doing remote execution (in fact, all methods that
193 The main method for doing remote execution (in fact, all methods that
194 communicate with the engines are built on top of it), is :meth:`View.apply`.
194 communicate with the engines are built on top of it), is :meth:`View.apply`.
195
195
196 We strive to provide the cleanest interface we can, so `apply` has the following
196 We strive to provide the cleanest interface we can, so `apply` has the following
197 signature:
197 signature:
198
198
199 .. sourcecode:: python
199 .. sourcecode:: python
200
200
201 view.apply(f, *args, **kwargs)
201 view.apply(f, *args, **kwargs)
202
202
203 There are various ways to call functions with IPython, and these flags are set as
203 There are various ways to call functions with IPython, and these flags are set as
204 attributes of the View. The ``DirectView`` has just two of these flags:
204 attributes of the View. The ``DirectView`` has just two of these flags:
205
205
206 dv.block : bool
206 dv.block : bool
207 whether to wait for the result, or return an :class:`AsyncResult` object
207 whether to wait for the result, or return an :class:`AsyncResult` object
208 immediately
208 immediately
209 dv.track : bool
209 dv.track : bool
210 whether to instruct pyzmq to track when zeromq is done sending the message.
210 whether to instruct pyzmq to track when zeromq is done sending the message.
211 This is primarily useful for non-copying sends of numpy arrays that you plan to
211 This is primarily useful for non-copying sends of numpy arrays that you plan to
212 edit in-place. You need to know when it becomes safe to edit the buffer
212 edit in-place. You need to know when it becomes safe to edit the buffer
213 without corrupting the message.
213 without corrupting the message.
214 dv.targets : int, list of ints
214 dv.targets : int, list of ints
215 which targets this view is associated with.
215 which targets this view is associated with.
216
216
217
217
218 Creating a view is simple: index-access on a client creates a :class:`.DirectView`.
218 Creating a view is simple: index-access on a client creates a :class:`.DirectView`.
219
219
220 .. sourcecode:: ipython
220 .. sourcecode:: ipython
221
221
222 In [4]: view = rc[1:3]
222 In [4]: view = rc[1:3]
223 Out[4]: <DirectView [1, 2]>
223 Out[4]: <DirectView [1, 2]>
224
224
225 In [5]: view.apply<tab>
225 In [5]: view.apply<tab>
226 view.apply view.apply_async view.apply_sync
226 view.apply view.apply_async view.apply_sync
227
227
228 For convenience, you can set block temporarily for a single call with the extra sync/async methods.
228 For convenience, you can set block temporarily for a single call with the extra sync/async methods.
229
229
230 Blocking execution
230 Blocking execution
231 ------------------
231 ------------------
232
232
233 In blocking mode, the :class:`.DirectView` object (called ``dview`` in
233 In blocking mode, the :class:`.DirectView` object (called ``dview`` in
234 these examples) submits the command to the controller, which places the
234 these examples) submits the command to the controller, which places the
235 command in the engines' queues for execution. The :meth:`apply` call then
235 command in the engines' queues for execution. The :meth:`apply` call then
236 blocks until the engines are done executing the command:
236 blocks until the engines are done executing the command:
237
237
238 .. sourcecode:: ipython
238 .. sourcecode:: ipython
239
239
240 In [2]: dview = rc[:] # A DirectView of all engines
240 In [2]: dview = rc[:] # A DirectView of all engines
241 In [3]: dview.block=True
241 In [3]: dview.block=True
242 In [4]: dview['a'] = 5
242 In [4]: dview['a'] = 5
243
243
244 In [5]: dview['b'] = 10
244 In [5]: dview['b'] = 10
245
245
246 In [6]: dview.apply(lambda x: a+b+x, 27)
246 In [6]: dview.apply(lambda x: a+b+x, 27)
247 Out[6]: [42, 42, 42, 42]
247 Out[6]: [42, 42, 42, 42]
248
248
249 You can also select blocking execution on a call-by-call basis with the :meth:`apply_sync`
249 You can also select blocking execution on a call-by-call basis with the :meth:`apply_sync`
250 method:
250 method:
251
251
252 .. sourcecode:: ipython
252 .. sourcecode:: ipython
253
253
254 In [7]: dview.block=False
254 In [7]: dview.block=False
255
255
256 In [8]: dview.apply_sync(lambda x: a+b+x, 27)
256 In [8]: dview.apply_sync(lambda x: a+b+x, 27)
257 Out[8]: [42, 42, 42, 42]
257 Out[8]: [42, 42, 42, 42]
258
258
259 Python commands can be executed as strings on specific engines by using a View's ``execute``
259 Python commands can be executed as strings on specific engines by using a View's ``execute``
260 method:
260 method:
261
261
262 .. sourcecode:: ipython
262 .. sourcecode:: ipython
263
263
264 In [6]: rc[::2].execute('c=a+b')
264 In [6]: rc[::2].execute('c=a+b')
265
265
266 In [7]: rc[1::2].execute('c=a-b')
266 In [7]: rc[1::2].execute('c=a-b')
267
267
268 In [8]: dview['c'] # shorthand for dview.pull('c', block=True)
268 In [8]: dview['c'] # shorthand for dview.pull('c', block=True)
269 Out[8]: [15, -5, 15, -5]
269 Out[8]: [15, -5, 15, -5]
270
270
271
271
272 Non-blocking execution
272 Non-blocking execution
273 ----------------------
273 ----------------------
274
274
275 In non-blocking mode, :meth:`apply` submits the command to be executed and
275 In non-blocking mode, :meth:`apply` submits the command to be executed and
276 then returns a :class:`AsyncResult` object immediately. The
276 then returns a :class:`AsyncResult` object immediately. The
277 :class:`AsyncResult` object gives you a way of getting a result at a later
277 :class:`AsyncResult` object gives you a way of getting a result at a later
278 time through its :meth:`get` method.
278 time through its :meth:`get` method.
279
279
280 .. seealso::
280 .. seealso::
281
281
282 Docs on the :ref:`AsyncResult <parallel_asyncresult>` object.
282 Docs on the :ref:`AsyncResult <parallel_asyncresult>` object.
283
283
284 This allows you to quickly submit long running commands without blocking your
284 This allows you to quickly submit long running commands without blocking your
285 local Python/IPython session:
285 local Python/IPython session:
286
286
287 .. sourcecode:: ipython
287 .. sourcecode:: ipython
288
288
289 # define our function
289 # define our function
290 In [6]: def wait(t):
290 In [6]: def wait(t):
291 ....: import time
291 ....: import time
292 ....: tic = time.time()
292 ....: tic = time.time()
293 ....: time.sleep(t)
293 ....: time.sleep(t)
294 ....: return time.time()-tic
294 ....: return time.time()-tic
295
295
296 # In non-blocking mode
296 # In non-blocking mode
297 In [7]: ar = dview.apply_async(wait, 2)
297 In [7]: ar = dview.apply_async(wait, 2)
298
298
299 # Now block for the result
299 # Now block for the result
300 In [8]: ar.get()
300 In [8]: ar.get()
301 Out[8]: [2.0006198883056641, 1.9997570514678955, 1.9996809959411621, 2.0003249645233154]
301 Out[8]: [2.0006198883056641, 1.9997570514678955, 1.9996809959411621, 2.0003249645233154]
302
302
303 # Again in non-blocking mode
303 # Again in non-blocking mode
304 In [9]: ar = dview.apply_async(wait, 10)
304 In [9]: ar = dview.apply_async(wait, 10)
305
305
306 # Poll to see if the result is ready
306 # Poll to see if the result is ready
307 In [10]: ar.ready()
307 In [10]: ar.ready()
308 Out[10]: False
308 Out[10]: False
309
309
310 # ask for the result, but wait a maximum of 1 second:
310 # ask for the result, but wait a maximum of 1 second:
311 In [45]: ar.get(1)
311 In [45]: ar.get(1)
312 ---------------------------------------------------------------------------
312 ---------------------------------------------------------------------------
313 TimeoutError Traceback (most recent call last)
313 TimeoutError Traceback (most recent call last)
314 /home/you/<ipython-input-45-7cd858bbb8e0> in <module>()
314 /home/you/<ipython-input-45-7cd858bbb8e0> in <module>()
315 ----> 1 ar.get(1)
315 ----> 1 ar.get(1)
316
316
317 /path/to/site-packages/IPython/parallel/asyncresult.pyc in get(self, timeout)
317 /path/to/site-packages/IPython/parallel/asyncresult.pyc in get(self, timeout)
318 62 raise self._exception
318 62 raise self._exception
319 63 else:
319 63 else:
320 ---> 64 raise error.TimeoutError("Result not ready.")
320 ---> 64 raise error.TimeoutError("Result not ready.")
321 65
321 65
322 66 def ready(self):
322 66 def ready(self):
323
323
324 TimeoutError: Result not ready.
324 TimeoutError: Result not ready.
325
325
326 .. Note::
326 .. Note::
327
327
328 Note the import inside the function. This is a common model, to ensure
328 Note the import inside the function. This is a common model, to ensure
329 that the appropriate modules are imported where the task is run. You can
329 that the appropriate modules are imported where the task is run. You can
330 also manually import modules into the engine(s) namespace(s) via
330 also manually import modules into the engine(s) namespace(s) via
331 :meth:`view.execute('import numpy')`.
331 :meth:`view.execute('import numpy')`.
332
332
333 Often, it is desirable to wait until a set of :class:`AsyncResult` objects
333 Often, it is desirable to wait until a set of :class:`AsyncResult` objects
334 are done. For this, there is a the method :meth:`wait`. This method takes a
334 are done. For this, there is a the method :meth:`wait`. This method takes a
335 tuple of :class:`AsyncResult` objects (or `msg_ids` or indices to the client's History),
335 tuple of :class:`AsyncResult` objects (or `msg_ids` or indices to the client's History),
336 and blocks until all of the associated results are ready:
336 and blocks until all of the associated results are ready:
337
337
338 .. sourcecode:: ipython
338 .. sourcecode:: ipython
339
339
340 In [72]: dview.block=False
340 In [72]: dview.block=False
341
341
342 # A trivial list of AsyncResults objects
342 # A trivial list of AsyncResults objects
343 In [73]: pr_list = [dview.apply_async(wait, 3) for i in range(10)]
343 In [73]: pr_list = [dview.apply_async(wait, 3) for i in range(10)]
344
344
345 # Wait until all of them are done
345 # Wait until all of them are done
346 In [74]: dview.wait(pr_list)
346 In [74]: dview.wait(pr_list)
347
347
348 # Then, their results are ready using get() or the `.r` attribute
348 # Then, their results are ready using get() or the `.r` attribute
349 In [75]: pr_list[0].get()
349 In [75]: pr_list[0].get()
350 Out[75]: [2.9982571601867676, 2.9982588291168213, 2.9987530708312988, 2.9990990161895752]
350 Out[75]: [2.9982571601867676, 2.9982588291168213, 2.9987530708312988, 2.9990990161895752]
351
351
352
352
353
353
354 The ``block`` and ``targets`` keyword arguments and attributes
354 The ``block`` and ``targets`` keyword arguments and attributes
355 --------------------------------------------------------------
355 --------------------------------------------------------------
356
356
357 Most DirectView methods (excluding :meth:`apply`) accept ``block`` and
357 Most DirectView methods (excluding :meth:`apply`) accept ``block`` and
358 ``targets`` as keyword arguments. As we have seen above, these keyword arguments control the
358 ``targets`` as keyword arguments. As we have seen above, these keyword arguments control the
359 blocking mode and which engines the command is applied to. The :class:`View` class also has
359 blocking mode and which engines the command is applied to. The :class:`View` class also has
360 :attr:`block` and :attr:`targets` attributes that control the default behavior when the keyword
360 :attr:`block` and :attr:`targets` attributes that control the default behavior when the keyword
361 arguments are not provided. Thus the following logic is used for :attr:`block` and :attr:`targets`:
361 arguments are not provided. Thus the following logic is used for :attr:`block` and :attr:`targets`:
362
362
363 * If no keyword argument is provided, the instance attributes are used.
363 * If no keyword argument is provided, the instance attributes are used.
364 * The Keyword arguments, if provided overrides the instance attributes for
364 * The Keyword arguments, if provided overrides the instance attributes for
365 the duration of a single call.
365 the duration of a single call.
366
366
367 The following examples demonstrate how to use the instance attributes:
367 The following examples demonstrate how to use the instance attributes:
368
368
369 .. sourcecode:: ipython
369 .. sourcecode:: ipython
370
370
371 In [16]: dview.targets = [0,2]
371 In [16]: dview.targets = [0,2]
372
372
373 In [17]: dview.block = False
373 In [17]: dview.block = False
374
374
375 In [18]: ar = dview.apply(lambda : 10)
375 In [18]: ar = dview.apply(lambda : 10)
376
376
377 In [19]: ar.get()
377 In [19]: ar.get()
378 Out[19]: [10, 10]
378 Out[19]: [10, 10]
379
379
380 In [20]: dview.targets = v.client.ids # all engines (4)
380 In [20]: dview.targets = v.client.ids # all engines (4)
381
381
382 In [21]: dview.block = True
382 In [21]: dview.block = True
383
383
384 In [22]: dview.apply(lambda : 42)
384 In [22]: dview.apply(lambda : 42)
385 Out[22]: [42, 42, 42, 42]
385 Out[22]: [42, 42, 42, 42]
386
386
387 The :attr:`block` and :attr:`targets` instance attributes of the
387 The :attr:`block` and :attr:`targets` instance attributes of the
388 :class:`.DirectView` also determine the behavior of the parallel magic commands.
388 :class:`.DirectView` also determine the behavior of the parallel magic commands.
389
389
390 Parallel magic commands
390 Parallel magic commands
391 -----------------------
391 -----------------------
392
392
393 We provide a few IPython magic commands (``%px``, ``%autopx`` and ``%result``)
393 We provide a few IPython magic commands (``%px``, ``%autopx`` and ``%result``)
394 that make it a bit more pleasant to execute Python commands on the engines interactively.
394 that make it a bit more pleasant to execute Python commands on the engines interactively.
395 These are simply shortcuts to :meth:`.DirectView.execute`
395 These are simply shortcuts to :meth:`.DirectView.execute`
396 and :meth:`.AsyncResult.display_outputs` methods repsectively.
396 and :meth:`.AsyncResult.display_outputs` methods repsectively.
397 The ``%px`` magic executes a single Python command on the engines
397 The ``%px`` magic executes a single Python command on the engines
398 specified by the :attr:`targets` attribute of the :class:`DirectView` instance:
398 specified by the :attr:`targets` attribute of the :class:`DirectView` instance:
399
399
400 .. sourcecode:: ipython
400 .. sourcecode:: ipython
401
401
402 # Create a DirectView for all targets
402 # Create a DirectView for all targets
403 In [22]: dv = rc[:]
403 In [22]: dv = rc[:]
404
404
405 # Make this DirectView active for parallel magic commands
405 # Make this DirectView active for parallel magic commands
406 In [23]: dv.activate()
406 In [23]: dv.activate()
407
407
408 In [24]: dv.block=True
408 In [24]: dv.block=True
409
409
410 # import numpy here and everywhere
410 # import numpy here and everywhere
411 In [25]: with dv.sync_imports():
411 In [25]: with dv.sync_imports():
412 ....: import numpy
412 ....: import numpy
413 importing numpy on engine(s)
413 importing numpy on engine(s)
414
414
415 In [27]: %px a = numpy.random.rand(2,2)
415 In [27]: %px a = numpy.random.rand(2,2)
416 Parallel execution on engines: [0, 1, 2, 3]
416 Parallel execution on engines: [0, 1, 2, 3]
417
417
418 In [28]: %px numpy.linalg.eigvals(a)
418 In [28]: %px numpy.linalg.eigvals(a)
419 Parallel execution on engines: [0, 1, 2, 3]
419 Parallel execution on engines: [0, 1, 2, 3]
420 [0] Out[68]: array([ 0.77120707, -0.19448286])
420 [0] Out[68]: array([ 0.77120707, -0.19448286])
421 [1] Out[68]: array([ 1.10815921, 0.05110369])
421 [1] Out[68]: array([ 1.10815921, 0.05110369])
422 [2] Out[68]: array([ 0.74625527, -0.37475081])
422 [2] Out[68]: array([ 0.74625527, -0.37475081])
423 [3] Out[68]: array([ 0.72931905, 0.07159743])
423 [3] Out[68]: array([ 0.72931905, 0.07159743])
424
424
425 In [29]: %px print 'hi'
425 In [29]: %px print 'hi'
426 Parallel execution on engine(s): [0, 1, 2, 3]
426 Parallel execution on engine(s): [0, 1, 2, 3]
427 [stdout:0] hi
427 [stdout:0] hi
428 [stdout:1] hi
428 [stdout:1] hi
429 [stdout:2] hi
429 [stdout:2] hi
430 [stdout:3] hi
430 [stdout:3] hi
431
431
432
432
433 Since engines are IPython as well, you can even run magics remotely:
433 Since engines are IPython as well, you can even run magics remotely:
434
434
435 .. sourcecode:: ipython
435 .. sourcecode:: ipython
436
436
437 In [28]: %px %pylab inline
437 In [28]: %px %pylab inline
438 Parallel execution on engine(s): [0, 1, 2, 3]
438 Parallel execution on engine(s): [0, 1, 2, 3]
439 [stdout:0]
439 [stdout:0]
440 Welcome to pylab, a matplotlib-based Python environment...
440 Welcome to pylab, a matplotlib-based Python environment...
441 For more information, type 'help(pylab)'.
441 For more information, type 'help(pylab)'.
442 [stdout:1]
442 [stdout:1]
443 Welcome to pylab, a matplotlib-based Python environment...
443 Welcome to pylab, a matplotlib-based Python environment...
444 For more information, type 'help(pylab)'.
444 For more information, type 'help(pylab)'.
445 [stdout:2]
445 [stdout:2]
446 Welcome to pylab, a matplotlib-based Python environment...
446 Welcome to pylab, a matplotlib-based Python environment...
447 For more information, type 'help(pylab)'.
447 For more information, type 'help(pylab)'.
448 [stdout:3]
448 [stdout:3]
449 Welcome to pylab, a matplotlib-based Python environment...
449 Welcome to pylab, a matplotlib-based Python environment...
450 For more information, type 'help(pylab)'.
450 For more information, type 'help(pylab)'.
451
451
452 And once in pylab mode with the inline backend,
452 And once in pylab mode with the inline backend,
453 you can make plots and they will be displayed in your frontend
453 you can make plots and they will be displayed in your frontend
454 if it suports the inline figures (e.g. notebook or qtconsole):
454 if it suports the inline figures (e.g. notebook or qtconsole):
455
455
456 .. sourcecode:: ipython
456 .. sourcecode:: ipython
457
457
458 In [40]: %px plot(rand(100))
458 In [40]: %px plot(rand(100))
459 Parallel execution on engine(s): [0, 1, 2, 3]
459 Parallel execution on engine(s): [0, 1, 2, 3]
460 <plot0>
460 <plot0>
461 <plot1>
461 <plot1>
462 <plot2>
462 <plot2>
463 <plot3>
463 <plot3>
464 [0] Out[79]: [<matplotlib.lines.Line2D at 0x10a6286d0>]
464 [0] Out[79]: [<matplotlib.lines.Line2D at 0x10a6286d0>]
465 [1] Out[79]: [<matplotlib.lines.Line2D at 0x10b9476d0>]
465 [1] Out[79]: [<matplotlib.lines.Line2D at 0x10b9476d0>]
466 [2] Out[79]: [<matplotlib.lines.Line2D at 0x110652750>]
466 [2] Out[79]: [<matplotlib.lines.Line2D at 0x110652750>]
467 [3] Out[79]: [<matplotlib.lines.Line2D at 0x10c6566d0>]
467 [3] Out[79]: [<matplotlib.lines.Line2D at 0x10c6566d0>]
468
468
469
469
470 ``%%px`` Cell Magic
470 ``%%px`` Cell Magic
471 *******************
471 *******************
472
472
473 `%%px` can also be used as a Cell Magic, which accepts ``--[no]block`` flags,
473 `%%px` can also be used as a Cell Magic, which accepts ``--[no]block`` flags,
474 and a ``--group-outputs`` argument, which adjust how the outputs of multiple
474 and a ``--group-outputs`` argument, which adjust how the outputs of multiple
475 engines are presented.
475 engines are presented.
476
476
477 .. seealso::
477 .. seealso::
478
478
479 :meth:`.AsyncResult.display_outputs` for the grouping options.
479 :meth:`.AsyncResult.display_outputs` for the grouping options.
480
480
481 .. sourcecode:: ipython
481 .. sourcecode:: ipython
482
482
483 In [50]: %%px --block --group-outputs=engine
483 In [50]: %%px --block --group-outputs=engine
484 ....: import numpy as np
484 ....: import numpy as np
485 ....: A = np.random.random((2,2))
485 ....: A = np.random.random((2,2))
486 ....: ev = numpy.linalg.eigvals(A)
486 ....: ev = numpy.linalg.eigvals(A)
487 ....: print ev
487 ....: print ev
488 ....: ev.max()
488 ....: ev.max()
489 ....:
489 ....:
490 Parallel execution on engine(s): [0, 1, 2, 3]
490 Parallel execution on engine(s): [0, 1, 2, 3]
491 [stdout:0] [ 0.60640442 0.95919621]
491 [stdout:0] [ 0.60640442 0.95919621]
492 [0] Out[73]: 0.9591962130899806
492 [0] Out[73]: 0.9591962130899806
493 [stdout:1] [ 0.38501813 1.29430871]
493 [stdout:1] [ 0.38501813 1.29430871]
494 [1] Out[73]: 1.2943087091452372
494 [1] Out[73]: 1.2943087091452372
495 [stdout:2] [-0.85925141 0.9387692 ]
495 [stdout:2] [-0.85925141 0.9387692 ]
496 [2] Out[73]: 0.93876920456230284
496 [2] Out[73]: 0.93876920456230284
497 [stdout:3] [ 0.37998269 1.24218246]
497 [stdout:3] [ 0.37998269 1.24218246]
498 [3] Out[73]: 1.2421824618493817
498 [3] Out[73]: 1.2421824618493817
499
499
500 ``%result`` Magic
500 ``%result`` Magic
501 *****************
501 *****************
502
502
503 If you are using ``%px`` in non-blocking mode, you won't get output.
503 If you are using ``%px`` in non-blocking mode, you won't get output.
504 You can use ``%result`` to display the outputs of the latest command,
504 You can use ``%result`` to display the outputs of the latest command,
505 just as is done when ``%px`` is blocking:
505 just as is done when ``%px`` is blocking:
506
506
507 .. sourcecode:: ipython
507 .. sourcecode:: ipython
508
508
509 In [39]: dv.block = False
509 In [39]: dv.block = False
510
510
511 In [40]: %px print 'hi'
511 In [40]: %px print 'hi'
512 Async parallel execution on engine(s): [0, 1, 2, 3]
512 Async parallel execution on engine(s): [0, 1, 2, 3]
513
513
514 In [41]: %result
514 In [41]: %result
515 [stdout:0] hi
515 [stdout:0] hi
516 [stdout:1] hi
516 [stdout:1] hi
517 [stdout:2] hi
517 [stdout:2] hi
518 [stdout:3] hi
518 [stdout:3] hi
519
519
520 ``%result`` simply calls :meth:`.AsyncResult.display_outputs` on the most recent request.
520 ``%result`` simply calls :meth:`.AsyncResult.display_outputs` on the most recent request.
521 You can pass integers as indices if you want a result other than the latest,
521 You can pass integers as indices if you want a result other than the latest,
522 e.g. ``%result -2``, or ``%result 0`` for the first.
522 e.g. ``%result -2``, or ``%result 0`` for the first.
523
523
524
524
525 ``%autopx``
525 ``%autopx``
526 ***********
526 ***********
527
527
528 The ``%autopx`` magic switches to a mode where everything you type is executed
528 The ``%autopx`` magic switches to a mode where everything you type is executed
529 on the engines until you do ``%autopx`` again.
529 on the engines until you do ``%autopx`` again.
530
530
531 .. sourcecode:: ipython
531 .. sourcecode:: ipython
532
532
533 In [30]: dv.block=True
533 In [30]: dv.block=True
534
534
535 In [31]: %autopx
535 In [31]: %autopx
536 %autopx enabled
536 %autopx enabled
537
537
538 In [32]: max_evals = []
538 In [32]: max_evals = []
539
539
540 In [33]: for i in range(100):
540 In [33]: for i in range(100):
541 ....: a = numpy.random.rand(10,10)
541 ....: a = numpy.random.rand(10,10)
542 ....: a = a+a.transpose()
542 ....: a = a+a.transpose()
543 ....: evals = numpy.linalg.eigvals(a)
543 ....: evals = numpy.linalg.eigvals(a)
544 ....: max_evals.append(evals[0].real)
544 ....: max_evals.append(evals[0].real)
545 ....:
545 ....:
546
546
547 In [34]: print "Average max eigenvalue is: %f" % (sum(max_evals)/len(max_evals))
547 In [34]: print "Average max eigenvalue is: %f" % (sum(max_evals)/len(max_evals))
548 [stdout:0] Average max eigenvalue is: 10.193101
548 [stdout:0] Average max eigenvalue is: 10.193101
549 [stdout:1] Average max eigenvalue is: 10.064508
549 [stdout:1] Average max eigenvalue is: 10.064508
550 [stdout:2] Average max eigenvalue is: 10.055724
550 [stdout:2] Average max eigenvalue is: 10.055724
551 [stdout:3] Average max eigenvalue is: 10.086876
551 [stdout:3] Average max eigenvalue is: 10.086876
552
552
553 In [35]: %autopx
553 In [35]: %autopx
554 Auto Parallel Disabled
554 Auto Parallel Disabled
555
555
556
556
557 Engines as Kernels
558 ******************
559
560 Engines are really the same object as the Kernels used elsewhere in IPython,
561 with the minor exception that engines connect to a controller, while regular kernels
562 bind their sockets, listening for connections from a QtConsole or other frontends.
563
564 Sometimes for debugging or inspection purposes, you would like a QtConsole connected
565 to an engine for more direct interaction. You can do this by first instructing
566 the Engine to *also* bind its kernel, to listen for connections:
567
568 .. sourcecode:: ipython
569
570 In [50]: %px from IPython.parallel import bind_kernel; bind_kernel()
571
572 Then, if your engines are local, you can start a qtconsole right on the engine(s):
573
574 .. sourcecode:: ipython
575
576 In [51]: %px %qtconsole
577
578 Careful with this one, because if your view is of 16 engines it will start 16 QtConsoles!
579
580 Or you can view just the connection info, and work out the right way to connect to the engines,
581 depending on where they live and where you are:
582
583 .. sourcecode:: ipython
584
585 In [51]: %px %connect_info
586 Parallel execution on engine(s): [0, 1, 2, 3]
587 [stdout:0]
588 {
589 "stdin_port": 60387,
590 "ip": "127.0.0.1",
591 "hb_port": 50835,
592 "key": "eee2dd69-7dd3-4340-bf3e-7e2e22a62542",
593 "shell_port": 55328,
594 "iopub_port": 58264
595 }
596
597 Paste the above JSON into a file, and connect with:
598 $> ipython <app> --existing <file>
599 or, if you are local, you can connect with just:
600 $> ipython <app> --existing kernel-60125.json
601 or even just:
602 $> ipython <app> --existing
603 if this is the most recent IPython session you have started.
604 [stdout:1]
605 {
606 "stdin_port": 61869,
607 ...
608
609 .. note::
610
611 ``%qtconsole`` will call :func:`bind_kernel` on an engine if it hasn't been done already,
612 so you can often skip that first step.
613
614
557 Moving Python objects around
615 Moving Python objects around
558 ============================
616 ============================
559
617
560 In addition to calling functions and executing code on engines, you can
618 In addition to calling functions and executing code on engines, you can
561 transfer Python objects to and from your IPython session and the engines. In
619 transfer Python objects to and from your IPython session and the engines. In
562 IPython, these operations are called :meth:`push` (sending an object to the
620 IPython, these operations are called :meth:`push` (sending an object to the
563 engines) and :meth:`pull` (getting an object from the engines).
621 engines) and :meth:`pull` (getting an object from the engines).
564
622
565 Basic push and pull
623 Basic push and pull
566 -------------------
624 -------------------
567
625
568 Here are some examples of how you use :meth:`push` and :meth:`pull`:
626 Here are some examples of how you use :meth:`push` and :meth:`pull`:
569
627
570 .. sourcecode:: ipython
628 .. sourcecode:: ipython
571
629
572 In [38]: dview.push(dict(a=1.03234,b=3453))
630 In [38]: dview.push(dict(a=1.03234,b=3453))
573 Out[38]: [None,None,None,None]
631 Out[38]: [None,None,None,None]
574
632
575 In [39]: dview.pull('a')
633 In [39]: dview.pull('a')
576 Out[39]: [ 1.03234, 1.03234, 1.03234, 1.03234]
634 Out[39]: [ 1.03234, 1.03234, 1.03234, 1.03234]
577
635
578 In [40]: dview.pull('b', targets=0)
636 In [40]: dview.pull('b', targets=0)
579 Out[40]: 3453
637 Out[40]: 3453
580
638
581 In [41]: dview.pull(('a','b'))
639 In [41]: dview.pull(('a','b'))
582 Out[41]: [ [1.03234, 3453], [1.03234, 3453], [1.03234, 3453], [1.03234, 3453] ]
640 Out[41]: [ [1.03234, 3453], [1.03234, 3453], [1.03234, 3453], [1.03234, 3453] ]
583
641
584 In [42]: dview.push(dict(c='speed'))
642 In [42]: dview.push(dict(c='speed'))
585 Out[42]: [None,None,None,None]
643 Out[42]: [None,None,None,None]
586
644
587 In non-blocking mode :meth:`push` and :meth:`pull` also return
645 In non-blocking mode :meth:`push` and :meth:`pull` also return
588 :class:`AsyncResult` objects:
646 :class:`AsyncResult` objects:
589
647
590 .. sourcecode:: ipython
648 .. sourcecode:: ipython
591
649
592 In [48]: ar = dview.pull('a', block=False)
650 In [48]: ar = dview.pull('a', block=False)
593
651
594 In [49]: ar.get()
652 In [49]: ar.get()
595 Out[49]: [1.03234, 1.03234, 1.03234, 1.03234]
653 Out[49]: [1.03234, 1.03234, 1.03234, 1.03234]
596
654
597
655
598 Dictionary interface
656 Dictionary interface
599 --------------------
657 --------------------
600
658
601 Since a Python namespace is just a :class:`dict`, :class:`DirectView` objects provide
659 Since a Python namespace is just a :class:`dict`, :class:`DirectView` objects provide
602 dictionary-style access by key and methods such as :meth:`get` and
660 dictionary-style access by key and methods such as :meth:`get` and
603 :meth:`update` for convenience. This make the remote namespaces of the engines
661 :meth:`update` for convenience. This make the remote namespaces of the engines
604 appear as a local dictionary. Underneath, these methods call :meth:`apply`:
662 appear as a local dictionary. Underneath, these methods call :meth:`apply`:
605
663
606 .. sourcecode:: ipython
664 .. sourcecode:: ipython
607
665
608 In [51]: dview['a']=['foo','bar']
666 In [51]: dview['a']=['foo','bar']
609
667
610 In [52]: dview['a']
668 In [52]: dview['a']
611 Out[52]: [ ['foo', 'bar'], ['foo', 'bar'], ['foo', 'bar'], ['foo', 'bar'] ]
669 Out[52]: [ ['foo', 'bar'], ['foo', 'bar'], ['foo', 'bar'], ['foo', 'bar'] ]
612
670
613 Scatter and gather
671 Scatter and gather
614 ------------------
672 ------------------
615
673
616 Sometimes it is useful to partition a sequence and push the partitions to
674 Sometimes it is useful to partition a sequence and push the partitions to
617 different engines. In MPI language, this is know as scatter/gather and we
675 different engines. In MPI language, this is know as scatter/gather and we
618 follow that terminology. However, it is important to remember that in
676 follow that terminology. However, it is important to remember that in
619 IPython's :class:`Client` class, :meth:`scatter` is from the
677 IPython's :class:`Client` class, :meth:`scatter` is from the
620 interactive IPython session to the engines and :meth:`gather` is from the
678 interactive IPython session to the engines and :meth:`gather` is from the
621 engines back to the interactive IPython session. For scatter/gather operations
679 engines back to the interactive IPython session. For scatter/gather operations
622 between engines, MPI, pyzmq, or some other direct interconnect should be used.
680 between engines, MPI, pyzmq, or some other direct interconnect should be used.
623
681
624 .. sourcecode:: ipython
682 .. sourcecode:: ipython
625
683
626 In [58]: dview.scatter('a',range(16))
684 In [58]: dview.scatter('a',range(16))
627 Out[58]: [None,None,None,None]
685 Out[58]: [None,None,None,None]
628
686
629 In [59]: dview['a']
687 In [59]: dview['a']
630 Out[59]: [ [0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15] ]
688 Out[59]: [ [0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15] ]
631
689
632 In [60]: dview.gather('a')
690 In [60]: dview.gather('a')
633 Out[60]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
691 Out[60]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
634
692
635 Other things to look at
693 Other things to look at
636 =======================
694 =======================
637
695
638 How to do parallel list comprehensions
696 How to do parallel list comprehensions
639 --------------------------------------
697 --------------------------------------
640
698
641 In many cases list comprehensions are nicer than using the map function. While
699 In many cases list comprehensions are nicer than using the map function. While
642 we don't have fully parallel list comprehensions, it is simple to get the
700 we don't have fully parallel list comprehensions, it is simple to get the
643 basic effect using :meth:`scatter` and :meth:`gather`:
701 basic effect using :meth:`scatter` and :meth:`gather`:
644
702
645 .. sourcecode:: ipython
703 .. sourcecode:: ipython
646
704
647 In [66]: dview.scatter('x',range(64))
705 In [66]: dview.scatter('x',range(64))
648
706
649 In [67]: %px y = [i**10 for i in x]
707 In [67]: %px y = [i**10 for i in x]
650 Parallel execution on engines: [0, 1, 2, 3]
708 Parallel execution on engines: [0, 1, 2, 3]
651
709
652 In [68]: y = dview.gather('y')
710 In [68]: y = dview.gather('y')
653
711
654 In [69]: print y
712 In [69]: print y
655 [0, 1, 1024, 59049, 1048576, 9765625, 60466176, 282475249, 1073741824,...]
713 [0, 1, 1024, 59049, 1048576, 9765625, 60466176, 282475249, 1073741824,...]
656
714
657 Remote imports
715 Remote imports
658 --------------
716 --------------
659
717
660 Sometimes you will want to import packages both in your interactive session
718 Sometimes you will want to import packages both in your interactive session
661 and on your remote engines. This can be done with the :class:`ContextManager`
719 and on your remote engines. This can be done with the :class:`ContextManager`
662 created by a DirectView's :meth:`sync_imports` method:
720 created by a DirectView's :meth:`sync_imports` method:
663
721
664 .. sourcecode:: ipython
722 .. sourcecode:: ipython
665
723
666 In [69]: with dview.sync_imports():
724 In [69]: with dview.sync_imports():
667 ....: import numpy
725 ....: import numpy
668 importing numpy on engine(s)
726 importing numpy on engine(s)
669
727
670 Any imports made inside the block will also be performed on the view's engines.
728 Any imports made inside the block will also be performed on the view's engines.
671 sync_imports also takes a `local` boolean flag that defaults to True, which specifies
729 sync_imports also takes a `local` boolean flag that defaults to True, which specifies
672 whether the local imports should also be performed. However, support for `local=False`
730 whether the local imports should also be performed. However, support for `local=False`
673 has not been implemented, so only packages that can be imported locally will work
731 has not been implemented, so only packages that can be imported locally will work
674 this way.
732 this way.
675
733
676 You can also specify imports via the ``@require`` decorator. This is a decorator
734 You can also specify imports via the ``@require`` decorator. This is a decorator
677 designed for use in Dependencies, but can be used to handle remote imports as well.
735 designed for use in Dependencies, but can be used to handle remote imports as well.
678 Modules or module names passed to ``@require`` will be imported before the decorated
736 Modules or module names passed to ``@require`` will be imported before the decorated
679 function is called. If they cannot be imported, the decorated function will never
737 function is called. If they cannot be imported, the decorated function will never
680 execute and will fail with an UnmetDependencyError. Failures of single Engines will
738 execute and will fail with an UnmetDependencyError. Failures of single Engines will
681 be collected and raise a CompositeError, as demonstrated in the next section.
739 be collected and raise a CompositeError, as demonstrated in the next section.
682
740
683 .. sourcecode:: ipython
741 .. sourcecode:: ipython
684
742
685 In [69]: from IPython.parallel import require
743 In [69]: from IPython.parallel import require
686
744
687 In [70]: @require('re'):
745 In [70]: @require('re'):
688 ....: def findall(pat, x):
746 ....: def findall(pat, x):
689 ....: # re is guaranteed to be available
747 ....: # re is guaranteed to be available
690 ....: return re.findall(pat, x)
748 ....: return re.findall(pat, x)
691
749
692 # you can also pass modules themselves, that you already have locally:
750 # you can also pass modules themselves, that you already have locally:
693 In [71]: @require(time):
751 In [71]: @require(time):
694 ....: def wait(t):
752 ....: def wait(t):
695 ....: time.sleep(t)
753 ....: time.sleep(t)
696 ....: return t
754 ....: return t
697
755
698 .. _parallel_exceptions:
756 .. _parallel_exceptions:
699
757
700 Parallel exceptions
758 Parallel exceptions
701 -------------------
759 -------------------
702
760
703 In the multiengine interface, parallel commands can raise Python exceptions,
761 In the multiengine interface, parallel commands can raise Python exceptions,
704 just like serial commands. But, it is a little subtle, because a single
762 just like serial commands. But, it is a little subtle, because a single
705 parallel command can actually raise multiple exceptions (one for each engine
763 parallel command can actually raise multiple exceptions (one for each engine
706 the command was run on). To express this idea, we have a
764 the command was run on). To express this idea, we have a
707 :exc:`CompositeError` exception class that will be raised in most cases. The
765 :exc:`CompositeError` exception class that will be raised in most cases. The
708 :exc:`CompositeError` class is a special type of exception that wraps one or
766 :exc:`CompositeError` class is a special type of exception that wraps one or
709 more other types of exceptions. Here is how it works:
767 more other types of exceptions. Here is how it works:
710
768
711 .. sourcecode:: ipython
769 .. sourcecode:: ipython
712
770
713 In [76]: dview.block=True
771 In [76]: dview.block=True
714
772
715 In [77]: dview.execute('1/0')
773 In [77]: dview.execute('1/0')
716 ---------------------------------------------------------------------------
774 ---------------------------------------------------------------------------
717 CompositeError Traceback (most recent call last)
775 CompositeError Traceback (most recent call last)
718 /home/user/<ipython-input-10-5d56b303a66c> in <module>()
776 /home/user/<ipython-input-10-5d56b303a66c> in <module>()
719 ----> 1 dview.execute('1/0')
777 ----> 1 dview.execute('1/0')
720
778
721 /path/to/site-packages/IPython/parallel/client/view.pyc in execute(self, code, targets, block)
779 /path/to/site-packages/IPython/parallel/client/view.pyc in execute(self, code, targets, block)
722 591 default: self.block
780 591 default: self.block
723 592 """
781 592 """
724 --> 593 return self._really_apply(util._execute, args=(code,), block=block, targets=targets)
782 --> 593 return self._really_apply(util._execute, args=(code,), block=block, targets=targets)
725 594
783 594
726 595 def run(self, filename, targets=None, block=None):
784 595 def run(self, filename, targets=None, block=None):
727
785
728 /home/user/<string> in _really_apply(self, f, args, kwargs, targets, block, track)
786 /home/user/<string> in _really_apply(self, f, args, kwargs, targets, block, track)
729
787
730 /path/to/site-packages/IPython/parallel/client/view.pyc in sync_results(f, self, *args, **kwargs)
788 /path/to/site-packages/IPython/parallel/client/view.pyc in sync_results(f, self, *args, **kwargs)
731 55 def sync_results(f, self, *args, **kwargs):
789 55 def sync_results(f, self, *args, **kwargs):
732 56 """sync relevant results from self.client to our results attribute."""
790 56 """sync relevant results from self.client to our results attribute."""
733 ---> 57 ret = f(self, *args, **kwargs)
791 ---> 57 ret = f(self, *args, **kwargs)
734 58 delta = self.outstanding.difference(self.client.outstanding)
792 58 delta = self.outstanding.difference(self.client.outstanding)
735 59 completed = self.outstanding.intersection(delta)
793 59 completed = self.outstanding.intersection(delta)
736
794
737 /home/user/<string> in _really_apply(self, f, args, kwargs, targets, block, track)
795 /home/user/<string> in _really_apply(self, f, args, kwargs, targets, block, track)
738
796
739 /path/to/site-packages/IPython/parallel/client/view.pyc in save_ids(f, self, *args, **kwargs)
797 /path/to/site-packages/IPython/parallel/client/view.pyc in save_ids(f, self, *args, **kwargs)
740 44 n_previous = len(self.client.history)
798 44 n_previous = len(self.client.history)
741 45 try:
799 45 try:
742 ---> 46 ret = f(self, *args, **kwargs)
800 ---> 46 ret = f(self, *args, **kwargs)
743 47 finally:
801 47 finally:
744 48 nmsgs = len(self.client.history) - n_previous
802 48 nmsgs = len(self.client.history) - n_previous
745
803
746 /path/to/site-packages/IPython/parallel/client/view.pyc in _really_apply(self, f, args, kwargs, targets, block, track)
804 /path/to/site-packages/IPython/parallel/client/view.pyc in _really_apply(self, f, args, kwargs, targets, block, track)
747 529 if block:
805 529 if block:
748 530 try:
806 530 try:
749 --> 531 return ar.get()
807 --> 531 return ar.get()
750 532 except KeyboardInterrupt:
808 532 except KeyboardInterrupt:
751 533 pass
809 533 pass
752
810
753 /path/to/site-packages/IPython/parallel/client/asyncresult.pyc in get(self, timeout)
811 /path/to/site-packages/IPython/parallel/client/asyncresult.pyc in get(self, timeout)
754 101 return self._result
812 101 return self._result
755 102 else:
813 102 else:
756 --> 103 raise self._exception
814 --> 103 raise self._exception
757 104 else:
815 104 else:
758 105 raise error.TimeoutError("Result not ready.")
816 105 raise error.TimeoutError("Result not ready.")
759
817
760 CompositeError: one or more exceptions from call to method: _execute
818 CompositeError: one or more exceptions from call to method: _execute
761 [0:apply]: ZeroDivisionError: integer division or modulo by zero
819 [0:apply]: ZeroDivisionError: integer division or modulo by zero
762 [1:apply]: ZeroDivisionError: integer division or modulo by zero
820 [1:apply]: ZeroDivisionError: integer division or modulo by zero
763 [2:apply]: ZeroDivisionError: integer division or modulo by zero
821 [2:apply]: ZeroDivisionError: integer division or modulo by zero
764 [3:apply]: ZeroDivisionError: integer division or modulo by zero
822 [3:apply]: ZeroDivisionError: integer division or modulo by zero
765
823
766 Notice how the error message printed when :exc:`CompositeError` is raised has
824 Notice how the error message printed when :exc:`CompositeError` is raised has
767 information about the individual exceptions that were raised on each engine.
825 information about the individual exceptions that were raised on each engine.
768 If you want, you can even raise one of these original exceptions:
826 If you want, you can even raise one of these original exceptions:
769
827
770 .. sourcecode:: ipython
828 .. sourcecode:: ipython
771
829
772 In [80]: try:
830 In [80]: try:
773 ....: dview.execute('1/0')
831 ....: dview.execute('1/0')
774 ....: except parallel.error.CompositeError, e:
832 ....: except parallel.error.CompositeError, e:
775 ....: e.raise_exception()
833 ....: e.raise_exception()
776 ....:
834 ....:
777 ....:
835 ....:
778 ---------------------------------------------------------------------------
836 ---------------------------------------------------------------------------
779 RemoteError Traceback (most recent call last)
837 RemoteError Traceback (most recent call last)
780 /home/user/<ipython-input-17-8597e7e39858> in <module>()
838 /home/user/<ipython-input-17-8597e7e39858> in <module>()
781 2 dview.execute('1/0')
839 2 dview.execute('1/0')
782 3 except CompositeError as e:
840 3 except CompositeError as e:
783 ----> 4 e.raise_exception()
841 ----> 4 e.raise_exception()
784
842
785 /path/to/site-packages/IPython/parallel/error.pyc in raise_exception(self, excid)
843 /path/to/site-packages/IPython/parallel/error.pyc in raise_exception(self, excid)
786 266 raise IndexError("an exception with index %i does not exist"%excid)
844 266 raise IndexError("an exception with index %i does not exist"%excid)
787 267 else:
845 267 else:
788 --> 268 raise RemoteError(en, ev, etb, ei)
846 --> 268 raise RemoteError(en, ev, etb, ei)
789 269
847 269
790 270
848 270
791
849
792 RemoteError: ZeroDivisionError(integer division or modulo by zero)
850 RemoteError: ZeroDivisionError(integer division or modulo by zero)
793 Traceback (most recent call last):
851 Traceback (most recent call last):
794 File "/path/to/site-packages/IPython/parallel/engine/streamkernel.py", line 330, in apply_request
852 File "/path/to/site-packages/IPython/parallel/engine/streamkernel.py", line 330, in apply_request
795 exec code in working,working
853 exec code in working,working
796 File "<string>", line 1, in <module>
854 File "<string>", line 1, in <module>
797 File "/path/to/site-packages/IPython/parallel/util.py", line 354, in _execute
855 File "/path/to/site-packages/IPython/parallel/util.py", line 354, in _execute
798 exec code in globals()
856 exec code in globals()
799 File "<string>", line 1, in <module>
857 File "<string>", line 1, in <module>
800 ZeroDivisionError: integer division or modulo by zero
858 ZeroDivisionError: integer division or modulo by zero
801
859
802 If you are working in IPython, you can simple type ``%debug`` after one of
860 If you are working in IPython, you can simple type ``%debug`` after one of
803 these :exc:`CompositeError` exceptions is raised, and inspect the exception
861 these :exc:`CompositeError` exceptions is raised, and inspect the exception
804 instance:
862 instance:
805
863
806 .. sourcecode:: ipython
864 .. sourcecode:: ipython
807
865
808 In [81]: dview.execute('1/0')
866 In [81]: dview.execute('1/0')
809 ---------------------------------------------------------------------------
867 ---------------------------------------------------------------------------
810 CompositeError Traceback (most recent call last)
868 CompositeError Traceback (most recent call last)
811 /home/user/<ipython-input-10-5d56b303a66c> in <module>()
869 /home/user/<ipython-input-10-5d56b303a66c> in <module>()
812 ----> 1 dview.execute('1/0')
870 ----> 1 dview.execute('1/0')
813
871
814 /path/to/site-packages/IPython/parallel/client/view.pyc in execute(self, code, targets, block)
872 /path/to/site-packages/IPython/parallel/client/view.pyc in execute(self, code, targets, block)
815 591 default: self.block
873 591 default: self.block
816 592 """
874 592 """
817 --> 593 return self._really_apply(util._execute, args=(code,), block=block, targets=targets)
875 --> 593 return self._really_apply(util._execute, args=(code,), block=block, targets=targets)
818 594
876 594
819 595 def run(self, filename, targets=None, block=None):
877 595 def run(self, filename, targets=None, block=None):
820
878
821 /home/user/<string> in _really_apply(self, f, args, kwargs, targets, block, track)
879 /home/user/<string> in _really_apply(self, f, args, kwargs, targets, block, track)
822
880
823 /path/to/site-packages/IPython/parallel/client/view.pyc in sync_results(f, self, *args, **kwargs)
881 /path/to/site-packages/IPython/parallel/client/view.pyc in sync_results(f, self, *args, **kwargs)
824 55 def sync_results(f, self, *args, **kwargs):
882 55 def sync_results(f, self, *args, **kwargs):
825 56 """sync relevant results from self.client to our results attribute."""
883 56 """sync relevant results from self.client to our results attribute."""
826 ---> 57 ret = f(self, *args, **kwargs)
884 ---> 57 ret = f(self, *args, **kwargs)
827 58 delta = self.outstanding.difference(self.client.outstanding)
885 58 delta = self.outstanding.difference(self.client.outstanding)
828 59 completed = self.outstanding.intersection(delta)
886 59 completed = self.outstanding.intersection(delta)
829
887
830 /home/user/<string> in _really_apply(self, f, args, kwargs, targets, block, track)
888 /home/user/<string> in _really_apply(self, f, args, kwargs, targets, block, track)
831
889
832 /path/to/site-packages/IPython/parallel/client/view.pyc in save_ids(f, self, *args, **kwargs)
890 /path/to/site-packages/IPython/parallel/client/view.pyc in save_ids(f, self, *args, **kwargs)
833 44 n_previous = len(self.client.history)
891 44 n_previous = len(self.client.history)
834 45 try:
892 45 try:
835 ---> 46 ret = f(self, *args, **kwargs)
893 ---> 46 ret = f(self, *args, **kwargs)
836 47 finally:
894 47 finally:
837 48 nmsgs = len(self.client.history) - n_previous
895 48 nmsgs = len(self.client.history) - n_previous
838
896
839 /path/to/site-packages/IPython/parallel/client/view.pyc in _really_apply(self, f, args, kwargs, targets, block, track)
897 /path/to/site-packages/IPython/parallel/client/view.pyc in _really_apply(self, f, args, kwargs, targets, block, track)
840 529 if block:
898 529 if block:
841 530 try:
899 530 try:
842 --> 531 return ar.get()
900 --> 531 return ar.get()
843 532 except KeyboardInterrupt:
901 532 except KeyboardInterrupt:
844 533 pass
902 533 pass
845
903
846 /path/to/site-packages/IPython/parallel/client/asyncresult.pyc in get(self, timeout)
904 /path/to/site-packages/IPython/parallel/client/asyncresult.pyc in get(self, timeout)
847 101 return self._result
905 101 return self._result
848 102 else:
906 102 else:
849 --> 103 raise self._exception
907 --> 103 raise self._exception
850 104 else:
908 104 else:
851 105 raise error.TimeoutError("Result not ready.")
909 105 raise error.TimeoutError("Result not ready.")
852
910
853 CompositeError: one or more exceptions from call to method: _execute
911 CompositeError: one or more exceptions from call to method: _execute
854 [0:apply]: ZeroDivisionError: integer division or modulo by zero
912 [0:apply]: ZeroDivisionError: integer division or modulo by zero
855 [1:apply]: ZeroDivisionError: integer division or modulo by zero
913 [1:apply]: ZeroDivisionError: integer division or modulo by zero
856 [2:apply]: ZeroDivisionError: integer division or modulo by zero
914 [2:apply]: ZeroDivisionError: integer division or modulo by zero
857 [3:apply]: ZeroDivisionError: integer division or modulo by zero
915 [3:apply]: ZeroDivisionError: integer division or modulo by zero
858
916
859 In [82]: %debug
917 In [82]: %debug
860 > /path/to/site-packages/IPython/parallel/client/asyncresult.py(103)get()
918 > /path/to/site-packages/IPython/parallel/client/asyncresult.py(103)get()
861 102 else:
919 102 else:
862 --> 103 raise self._exception
920 --> 103 raise self._exception
863 104 else:
921 104 else:
864
922
865 # With the debugger running, self._exception is the exceptions instance. We can tab complete
923 # With the debugger running, self._exception is the exceptions instance. We can tab complete
866 # on it and see the extra methods that are available.
924 # on it and see the extra methods that are available.
867 ipdb> self._exception.<tab>
925 ipdb> self._exception.<tab>
868 e.__class__ e.__getitem__ e.__new__ e.__setstate__ e.args
926 e.__class__ e.__getitem__ e.__new__ e.__setstate__ e.args
869 e.__delattr__ e.__getslice__ e.__reduce__ e.__str__ e.elist
927 e.__delattr__ e.__getslice__ e.__reduce__ e.__str__ e.elist
870 e.__dict__ e.__hash__ e.__reduce_ex__ e.__weakref__ e.message
928 e.__dict__ e.__hash__ e.__reduce_ex__ e.__weakref__ e.message
871 e.__doc__ e.__init__ e.__repr__ e._get_engine_str e.print_tracebacks
929 e.__doc__ e.__init__ e.__repr__ e._get_engine_str e.print_tracebacks
872 e.__getattribute__ e.__module__ e.__setattr__ e._get_traceback e.raise_exception
930 e.__getattribute__ e.__module__ e.__setattr__ e._get_traceback e.raise_exception
873 ipdb> self._exception.print_tracebacks()
931 ipdb> self._exception.print_tracebacks()
874 [0:apply]:
932 [0:apply]:
875 Traceback (most recent call last):
933 Traceback (most recent call last):
876 File "/path/to/site-packages/IPython/parallel/engine/streamkernel.py", line 330, in apply_request
934 File "/path/to/site-packages/IPython/parallel/engine/streamkernel.py", line 330, in apply_request
877 exec code in working,working
935 exec code in working,working
878 File "<string>", line 1, in <module>
936 File "<string>", line 1, in <module>
879 File "/path/to/site-packages/IPython/parallel/util.py", line 354, in _execute
937 File "/path/to/site-packages/IPython/parallel/util.py", line 354, in _execute
880 exec code in globals()
938 exec code in globals()
881 File "<string>", line 1, in <module>
939 File "<string>", line 1, in <module>
882 ZeroDivisionError: integer division or modulo by zero
940 ZeroDivisionError: integer division or modulo by zero
883
941
884
942
885 [1:apply]:
943 [1:apply]:
886 Traceback (most recent call last):
944 Traceback (most recent call last):
887 File "/path/to/site-packages/IPython/parallel/engine/streamkernel.py", line 330, in apply_request
945 File "/path/to/site-packages/IPython/parallel/engine/streamkernel.py", line 330, in apply_request
888 exec code in working,working
946 exec code in working,working
889 File "<string>", line 1, in <module>
947 File "<string>", line 1, in <module>
890 File "/path/to/site-packages/IPython/parallel/util.py", line 354, in _execute
948 File "/path/to/site-packages/IPython/parallel/util.py", line 354, in _execute
891 exec code in globals()
949 exec code in globals()
892 File "<string>", line 1, in <module>
950 File "<string>", line 1, in <module>
893 ZeroDivisionError: integer division or modulo by zero
951 ZeroDivisionError: integer division or modulo by zero
894
952
895
953
896 [2:apply]:
954 [2:apply]:
897 Traceback (most recent call last):
955 Traceback (most recent call last):
898 File "/path/to/site-packages/IPython/parallel/engine/streamkernel.py", line 330, in apply_request
956 File "/path/to/site-packages/IPython/parallel/engine/streamkernel.py", line 330, in apply_request
899 exec code in working,working
957 exec code in working,working
900 File "<string>", line 1, in <module>
958 File "<string>", line 1, in <module>
901 File "/path/to/site-packages/IPython/parallel/util.py", line 354, in _execute
959 File "/path/to/site-packages/IPython/parallel/util.py", line 354, in _execute
902 exec code in globals()
960 exec code in globals()
903 File "<string>", line 1, in <module>
961 File "<string>", line 1, in <module>
904 ZeroDivisionError: integer division or modulo by zero
962 ZeroDivisionError: integer division or modulo by zero
905
963
906
964
907 [3:apply]:
965 [3:apply]:
908 Traceback (most recent call last):
966 Traceback (most recent call last):
909 File "/path/to/site-packages/IPython/parallel/engine/streamkernel.py", line 330, in apply_request
967 File "/path/to/site-packages/IPython/parallel/engine/streamkernel.py", line 330, in apply_request
910 exec code in working,working
968 exec code in working,working
911 File "<string>", line 1, in <module>
969 File "<string>", line 1, in <module>
912 File "/path/to/site-packages/IPython/parallel/util.py", line 354, in _execute
970 File "/path/to/site-packages/IPython/parallel/util.py", line 354, in _execute
913 exec code in globals()
971 exec code in globals()
914 File "<string>", line 1, in <module>
972 File "<string>", line 1, in <module>
915 ZeroDivisionError: integer division or modulo by zero
973 ZeroDivisionError: integer division or modulo by zero
916
974
917
975
918 All of this same error handling magic even works in non-blocking mode:
976 All of this same error handling magic even works in non-blocking mode:
919
977
920 .. sourcecode:: ipython
978 .. sourcecode:: ipython
921
979
922 In [83]: dview.block=False
980 In [83]: dview.block=False
923
981
924 In [84]: ar = dview.execute('1/0')
982 In [84]: ar = dview.execute('1/0')
925
983
926 In [85]: ar.get()
984 In [85]: ar.get()
927 ---------------------------------------------------------------------------
985 ---------------------------------------------------------------------------
928 CompositeError Traceback (most recent call last)
986 CompositeError Traceback (most recent call last)
929 /home/user/<ipython-input-21-8531eb3d26fb> in <module>()
987 /home/user/<ipython-input-21-8531eb3d26fb> in <module>()
930 ----> 1 ar.get()
988 ----> 1 ar.get()
931
989
932 /path/to/site-packages/IPython/parallel/client/asyncresult.pyc in get(self, timeout)
990 /path/to/site-packages/IPython/parallel/client/asyncresult.pyc in get(self, timeout)
933 101 return self._result
991 101 return self._result
934 102 else:
992 102 else:
935 --> 103 raise self._exception
993 --> 103 raise self._exception
936 104 else:
994 104 else:
937 105 raise error.TimeoutError("Result not ready.")
995 105 raise error.TimeoutError("Result not ready.")
938
996
939 CompositeError: one or more exceptions from call to method: _execute
997 CompositeError: one or more exceptions from call to method: _execute
940 [0:apply]: ZeroDivisionError: integer division or modulo by zero
998 [0:apply]: ZeroDivisionError: integer division or modulo by zero
941 [1:apply]: ZeroDivisionError: integer division or modulo by zero
999 [1:apply]: ZeroDivisionError: integer division or modulo by zero
942 [2:apply]: ZeroDivisionError: integer division or modulo by zero
1000 [2:apply]: ZeroDivisionError: integer division or modulo by zero
943 [3:apply]: ZeroDivisionError: integer division or modulo by zero
1001 [3:apply]: ZeroDivisionError: integer division or modulo by zero
944
1002
General Comments 0
You need to be logged in to leave comments. Login now