##// END OF EJS Templates
docs include 'apply'
MinRK -
Show More
@@ -1,190 +1,193
1 1 .. _ip1par:
2 2
3 3 ============================
4 4 Overview and getting started
5 5 ============================
6 6
7 7 Introduction
8 8 ============
9 9
10 10 This section gives an overview of IPython's sophisticated and powerful
11 11 architecture for parallel and distributed computing. This architecture
12 12 abstracts out parallelism in a very general way, which enables IPython to
13 13 support many different styles of parallelism including:
14 14
15 15 * Single program, multiple data (SPMD) parallelism.
16 16 * Multiple program, multiple data (MPMD) parallelism.
17 17 * Message passing using MPI.
18 18 * Task farming.
19 19 * Data parallel.
20 20 * Combinations of these approaches.
21 21 * Custom user defined approaches.
22 22
23 23 Most importantly, IPython enables all types of parallel applications to
24 24 be developed, executed, debugged and monitored *interactively*. Hence,
25 25 the ``I`` in IPython. The following are some example usage cases for IPython:
26 26
27 27 * Quickly parallelize algorithms that are embarrassingly parallel
28 28 using a number of simple approaches. Many simple things can be
29 29 parallelized interactively in one or two lines of code.
30 30
31 31 * Steer traditional MPI applications on a supercomputer from an
32 32 IPython session on your laptop.
33 33
34 34 * Analyze and visualize large datasets (that could be remote and/or
35 35 distributed) interactively using IPython and tools like
36 36 matplotlib/TVTK.
37 37
38 38 * Develop, test and debug new parallel algorithms
39 39 (that may use MPI) interactively.
40 40
41 41 * Tie together multiple MPI jobs running on different systems into
42 42 one giant distributed and parallel system.
43 43
44 44 * Start a parallel job on your cluster and then have a remote
45 45 collaborator connect to it and pull back data into their
46 46 local IPython session for plotting and analysis.
47 47
48 48 * Run a set of tasks on a set of CPUs using dynamic load balancing.
49 49
50 50 Architecture overview
51 51 =====================
52 52
53 53 The IPython architecture consists of four components:
54 54
55 55 * The IPython engine.
56 56 * The IPython controller.
57 57 * The IPython scheduler.
58 58 * The controller client.
59 59
60 60 These components live in the :mod:`IPython.zmq.parallel` package and are
61 61 installed with IPython. They do, however, have additional dependencies
62 62 that must be installed. For more information, see our
63 63 :ref:`installation documentation <install_index>`.
64 64
65 65 .. TODO: include zmq in install_index
66 66
67 67 IPython engine
68 68 ---------------
69 69
70 70 The IPython engine is a Python instance that takes Python commands over a
71 71 network connection. Eventually, the IPython engine will be a full IPython
72 72 interpreter, but for now, it is a regular Python interpreter. The engine
73 73 can also handle incoming and outgoing Python objects sent over a network
74 74 connection. When multiple engines are started, parallel and distributed
75 75 computing becomes possible. An important feature of an IPython engine is
76 76 that it blocks while user code is being executed. Read on for how the
77 77 IPython controller solves this problem to expose a clean asynchronous API
78 78 to the user.
79 79
80 80 IPython controller
81 81 ------------------
82 82
83 83 The IPython controller provides an interface for working with a set of
84 84 engines. At an general level, the controller is a collection of processes to
85 85 which IPython engines can connect. For each connected engine, the controller
86 86 manages two queues. All actions that can be performed on the engine go through
87 87 this queue. While the engines themselves block when user code is run, the
88 88 controller hides that from the user to provide a fully asynchronous interface
89 89 to a set of engines.
90 90
91 91 The controller also provides a single point of contact for users who wish to
92 92 utilize the engines connected to the controller. There are different ways of
93 93 working with a controller. In IPython, all of these models are implemented via
94 94 the client's :meth:`.Client.apply` method, with various arguments, or
95 95 constructing :class:`.View` objects to represent subsets of engines. The two
96 96 primary models for interacting with engines are:
97 97
98 98 * A MUX interface, where engines are addressed explicitly.
99 99 * A Task interface, where the Scheduler is trusted with assigning work to
100 100 appropriate engines.
101 101
102 102 Advanced users can readily extend the View models to enable other
103 103 styles of parallelism.
104 104
105 105 .. note::
106 106
107 107 A single controller and set of engines can be used with multiple models
108 108 simultaneously. This opens the door for lots of interesting things.
109 109
110 110 Controller client
111 111 -----------------
112 112
113 113 There is one primary object, the :class:`~.parallel.client.Client`, for connecting to a controller. For each model, there is a corresponding view. These views allow users to interact with a set of engines through the
114 114 interface. Here are the two default views:
115 115
116 116 * The :class:`DirectView` class for explicit addressing.
117 117 * The :class:`LoadBalancedView` class for destination-agnostic scheduling.
118 118
119 119 Security
120 120 --------
121 121
122 122 IPython uses ZeroMQ for networking, which has provided many advantages, but
123 123 one of the setbacks is its utter lack of security [ZeroMQ]_. By default, no IPython
124 124 connections are secured, but open ports only listen on localhost. The only
125 125 source of security for IPython is via ssh-tunnel. IPython supports both shell
126 126 (`openssh`) and `paramiko` based tunnels for connections.
127 127
128 128 In our architecture, the controller is the only process that listens on
129 129 network ports, and is thus the main point of vulnerability. The standard model
130 130 for secure connections is to designate that the controller listen on
131 131 localhost, and use ssh-tunnels on the same machine to connect clients and/or
132 132 engines.
133 133
134 134 .. warning::
135 135
136 136 Even at its most secure, the Controller listens on ports on localhost, and
137 137 every time you make a tunnel, you open a localhost port on the connecting
138 138 machine that points to the Controller. If localhost on the Controller's
139 139 machine, or the machine of any client or engine, is untrusted, then your
140 140 Controller is insecure. There is no way around this with ZeroMQ.
141 141
142 142
143 143 .. TODO: edit parallelsecurity
144 144 A detailed description of the security model and its implementation in IPython
145 145 can be found :ref:`here <parallelsecurity>`.
146 146
147 147 Getting Started
148 148 ===============
149 149
150 150 To use IPython for parallel computing, you need to start one instance of the
151 151 controller and one or more instances of the engine. Initially, it is best to
152 152 simply start a controller and engines on a single host using the
153 153 :command:`ipclusterz` command. To start a controller and 4 engines on your
154 154 localhost, just do::
155 155
156 156 $ ipclusterz -n 4
157 157
158 158 More details about starting the IPython controller and engines can be found
159 159 :ref:`here <parallel_process>`
160 160
161 161 Once you have started the IPython controller and one or more engines, you
162 162 are ready to use the engines to do something useful. To make sure
163 163 everything is working correctly, try the following commands:
164 164
165 165 .. sourcecode:: ipython
166 166
167 167 In [1]: from IPython.zmq.parallel import client
168 168
169 169 In [2]: c = client.Client()
170 170
171 171 In [4]: c.ids
172 172 Out[4]: set([0, 1, 2, 3])
173 173
174 174 In [5]: c.apply(lambda : "Hello, World", targets='all', block=True)
175 175 Out[5]: {0: 'Hello, World', 1: 'Hello, World', 2: 'Hello, World', 3:
176 176 'Hello, World'}
177 177
178 Remember, a client needs to be able to see the Controller. So if the controller is on a different machine, and you have ssh access to that machine, then you would connect to it with::
178 Remember, a client needs to be able to see the Controller. So if the
179 controller is on a different machine, and you have ssh access to that machine,
180 then you would connect to it with::
179 181
180 182 .. sourcecode:: ipython
181 183
182 184 In [2]: c = client.Client(sshserver='mycontroller.example.com')
183 185
184 Where 'mycontroller.example.com' is the url or IP address of the machine on which the Controller is running.
186 Where 'mycontroller.example.com' is the url or IP address of the machine on
187 which the Controller is running.
185 188
186 189 You are now ready to learn more about the :ref:`MUX
187 190 <parallelmultiengine>` and :ref:`Task <paralleltask>` interfaces to the
188 191 controller.
189 192
190 193 .. [ZeroMQ] ZeroMQ. http://www.zeromq.org
@@ -1,785 +1,828
1 1 .. _parallelmultiengine:
2 2
3 3 ===============================
4 4 IPython's multiengine interface
5 5 ===============================
6 6
7 7 The multiengine interface represents one possible way of working with a set of
8 8 IPython engines. The basic idea behind the multiengine interface is that the
9 9 capabilities of each engine are directly and explicitly exposed to the user.
10 10 Thus, in the multiengine interface, each engine is given an id that is used to
11 11 identify the engine and give it work to do. This interface is very intuitive
12 12 and is designed with interactive usage in mind, and is thus the best place for
13 13 new users of IPython to begin.
14 14
15 15 Starting the IPython controller and engines
16 16 ===========================================
17 17
18 18 To follow along with this tutorial, you will need to start the IPython
19 19 controller and four IPython engines. The simplest way of doing this is to use
20 20 the :command:`ipclusterz` command::
21 21
22 22 $ ipclusterz -n 4
23 23
24 24 For more detailed information about starting the controller and engines, see
25 25 our :ref:`introduction <ip1par>` to using IPython for parallel computing.
26 26
27 27 Creating a ``Client`` instance
28 28 ==============================
29 29
30 30 The first step is to import the IPython :mod:`IPython.zmq.parallel.client`
31 31 module and then create a :class:`.Client` instance:
32 32
33 33 .. sourcecode:: ipython
34 34
35 35 In [1]: from IPython.zmq.parallel import client
36 36
37 37 In [2]: rc = client.Client()
38 38
39 39 This form assumes that the controller was started on localhost with default
40 40 configuration. If not, the location of the controller must be given as an
41 41 argument to the constructor:
42 42
43 43 .. sourcecode:: ipython
44 44
45 45 # for a visible LAN controller listening on an external port:
46 46 In [2]: rc = client.Client('tcp://192.168.1.16:10101')
47 47 # for a remote controller at my.server.com listening on localhost:
48 48 In [3]: rc = client.Client(sshserver='my.server.com')
49 49
50 50
51 51 To make sure there are engines connected to the controller, use can get a list
52 52 of engine ids:
53 53
54 54 .. sourcecode:: ipython
55 55
56 56 In [3]: rc.ids
57 57 Out[3]: set([0, 1, 2, 3])
58 58
59 59 Here we see that there are four engines ready to do work for us.
60 60
61 61 Quick and easy parallelism
62 62 ==========================
63 63
64 64 In many cases, you simply want to apply a Python function to a sequence of
65 65 objects, but *in parallel*. The client interface provides a simple way
66 66 of accomplishing this: useing the builtin :func:`map` and the ``@remote``
67 67 function decorator.
68 68
69 69 Parallel map
70 70 ------------
71 71
72 72 Python's builtin :func:`map` functions allows a function to be applied to a
73 73 sequence element-by-element. This type of code is typically trivial to
74 parallelize. In fact, since IPython's interface is all about functions anyway, you can just use the builtin :func:`map`, or a client's :map: method:
74 parallelize. In fact, since IPython's interface is all about functions anyway,
75 you can just use the builtin :func:`map`, or a client's :map: method:
75 76
76 77 .. sourcecode:: ipython
77 78
78 79 In [62]: serial_result = map(lambda x:x**10, range(32))
79 80
80 81 In [66]: parallel_result = rc.map(lambda x: x**10, range(32))
81 82
82 83 In [67]: serial_result==parallel_result
83 84 Out[67]: True
84 85
85 86
86 87 .. note::
87 88
88 89 The client's own version of :meth:`map` or that of :class:`.DirectView` do
89 90 not do any load balancing. For a load balanced version, use a
90 91 :class:`LoadBalancedView`, or a :class:`ParallelFunction` with
91 92 `targets=None`.
92 93
93 94 .. seealso::
94 95
95 96 :meth:`map` is implemented via :class:`.ParallelFunction`.
96 97
97 98 Remote function decorator
98 99 -------------------------
99 100
100 101 Remote functions are just like normal functions, but when they are called,
101 102 they execute on one or more engines, rather than locally. IPython provides
102 103 some decorators:
103 104
104 105 .. sourcecode:: ipython
105 106
106 107 In [10]: @rc.remote(block=True)
107 108 ....: def f(x):
108 109 ....: return 10.0*x**4
109 110 ....:
110 111
111 112 In [11]: map(f, range(32)) # this is done in parallel
112 113 Out[11]:
113 114 [0.0,10.0,160.0,...]
114 115
115 116 See the docstring for the :func:`parallel` and :func:`remote` decorators for
116 117 options.
117 118
118 119 Calling Python functions
119 120 ========================
120 121
121 122 The most basic type of operation that can be performed on the engines is to
122 123 execute Python code or call Python functions. Executing Python code can be
123 124 done in blocking or non-blocking mode (non-blocking is default) using the
124 125 :meth:`execute` method, and calling functions can be done via the
125 126 :meth:`.View.apply` method.
126 127
128 apply
129 -----
130
131 The main method for doing remote execution (in fact, all methods that
132 communicate with the engines are built on top of it), is :meth:`Client.apply`.
133 Ideally, :meth:`apply` would have the signature :meth:`apply(f,*args,**kwargs)`,
134 which would call f(*args,**kwargs) remotely. However, since :class:`Clients`
135 require some more options, they cannot reasonably provide this interface.
136 Instead, they provide the signature::
137
138 c.apply(f, args=None, kwargs=None, bound=True, block=None,
139 targets=None, after=None, follow=None)
140
141 In order to provide the nicer interface, we have :class:`View` classes, which wrap
142 :meth:`Client.apply` by using attributes and extra :meth:`apply_x` methods to determine
143 the extra arguments. For instance, performing index-access on a client creates a
144 :class:`.LoadBalancedView`.
145
146 .. sourcecode:: ipython
147
148 In [4]: view = rc[1:3]
149 Out[4]: <DirectView [1, 2]>
150
151 In [5]: view.apply<tab>
152 view.apply view.apply_async view.apply_async_bound view.apply_bound view.apply_sync view.apply_sync_bound
153
154 A :class:`DirectView` always uses its `targets` attribute, and it will use its `bound`
155 and `block` attributes in its :meth:`apply` method, but the suffixed :meth:`apply_x`
156 methods allow specifying `bound` and `block` via the different methods.
157
158 ================== ========== ==========
159 method block bound
160 ================== ========== ==========
161 apply self.block self.bound
162 apply_sync True False
163 apply_async False False
164 apply_sync_bound True True
165 apply_async_bound False True
166 ================== ========== ==========
167
168 For explanation of these values, read on.
169
127 170 Blocking execution
128 171 ------------------
129 172
130 173 In blocking mode, the :class:`.DirectView` object (called ``dview`` in
131 174 these examples) submits the command to the controller, which places the
132 175 command in the engines' queues for execution. The :meth:`apply` call then
133 176 blocks until the engines are done executing the command:
134 177
135 178 .. sourcecode:: ipython
136 179
137 180 In [2]: rc.block=True
138 181 In [3]: dview = rc[:] # A DirectView of all engines
139 182 In [4]: dview['a'] = 5
140 183
141 184
142 185 In [5]: dview['b'] = 10
143 186
144 187 In [6]: dview.apply_bound(lambda x: a+b+x, 27)
145 188 Out[6]: {0: 42, 1: 42, 2: 42, 3: 42}
146 189
147 190 Python commands can be executed on specific engines by calling execute using
148 191 the ``targets`` keyword argument, or creating a :class:`DirectView` instance
149 192 by index-access to the client:
150 193
151 194 .. sourcecode:: ipython
152 195
153 196 In [6]: rc.execute('c=a+b',targets=[0,2])
154 197
155 198 In [7]: rc.execute('c=a-b',targets=[1,3])
156 199
157 In [8]: rc[:]['c']
200 In [8]: rc[:]['c'] # shorthand for rc.pull('c',targets='all')
158 201 Out[8]: {0: 15, 1: -5, 2: 15, 3: -5}
159 202
160 203 .. note::
161 204
162 205 Note that every call to ``rc.<meth>(...,targets=x)`` can be made via
163 206 ``rc[<x>].<meth>(...)``, which constructs a View object. The only place
164 207 where this differs in in :meth:`apply`. The :class:`Client` takes many
165 208 arguments to apply, so it requires `args` and `kwargs` to be passed as
166 209 individual arguments. Extended options such as `bound`,`targets`, and
167 210 `block` are controlled by the attributes of the :class:`View` objects, so
168 211 they can provide the much more convenient
169 212 :meth:`View.apply(f,*args,**kwargs)`, which simply calls
170 213 ``f(*args,**kwargs)`` remotely.
171 214
172 215 This example also shows one of the most important things about the IPython
173 216 engines: they have a persistent user namespaces. The :meth:`apply` method can
174 217 be run in either a bound or unbound way. The default for a View is to be
175 218 unbound, unless called by the :meth:`apply_bound` method:
176 219
177 220 .. sourcecode:: ipython
178 221
179 222 In [9]: rc[:]['b'] = 5 # assign b to 5 everywhere
180 223
181 224 In [10]: v0 = rc[0]
182 225
183 226 In [12]: v0.apply_bound(lambda : b)
184 227 Out[12]: 5
185 228
186 229 In [13]: v0.apply(lambda : b)
187 230 ---------------------------------------------------------------------------
188 231 RemoteError Traceback (most recent call last)
189 232 /home/you/<ipython-input-34-21a468eb10f0> in <module>()
190 233 ----> 1 v0.apply(lambda : b)
191 234 ...
192 235 RemoteError: NameError(global name 'b' is not defined)
193 236 Traceback (most recent call last):
194 237 File "/Users/minrk/dev/ip/mine/IPython/zmq/parallel/streamkernel.py", line 294, in apply_request
195 238 exec code in working, working
196 239 File "<string>", line 1, in <module>
197 240 File "<ipython-input-34-21a468eb10f0>", line 1, in <lambda>
198 241 NameError: global name 'b' is not defined
199 242
200 243
201 244 Specifically, `bound=True` specifies that the engine's namespace is to be used
202 245 for execution, and `bound=False` specifies that the engine's namespace is not
203 246 to be used (hence, 'b' is undefined during unbound execution, since the
204 247 function is called in an empty namespace). Unbound execution is often useful
205 248 for large numbers of atomic tasks, which prevents bloating the engine's
206 249 memory, while bound execution lets you build on your previous work.
207 250
208 251
209 252 Non-blocking execution
210 253 ----------------------
211 254
212 255 In non-blocking mode, :meth:`apply` submits the command to be executed and
213 256 then returns a :class:`AsyncResult` object immediately. The
214 257 :class:`AsyncResult` object gives you a way of getting a result at a later
215 258 time through its :meth:`get` method.
216 259
217 260 .. Note::
218 261
219 262 The :class:`AsyncResult` object provides the exact same interface as
220 263 :py:class:`multiprocessing.pool.AsyncResult`. See the
221 264 `official Python documentation <http://docs.python.org/library/multiprocessing#multiprocessing.pool.AsyncResult>`_
222 265 for more.
223 266
224 267
225 268 This allows you to quickly submit long running commands without blocking your
226 269 local Python/IPython session:
227 270
228 271 .. sourcecode:: ipython
229 272
230 273 # define our function
231 274 In [35]: def wait(t):
232 275 ....: import time
233 276 ....: tic = time.time()
234 277 ....: time.sleep(t)
235 278 ....: return time.time()-tic
236 279
237 280 # In blocking mode
238 281 In [6]: rc.apply('import time')
239 282
240 283 # In non-blocking mode
241 284 In [7]: pr = rc[:].apply_async(wait, 2)
242 285
243 286 # Now block for the result
244 287 In [8]: pr.get()
245 288 Out[8]: [2.0006198883056641, 1.9997570514678955, 1.9996809959411621, 2.0003249645233154]
246 289
247 290 # Again in non-blocking mode
248 291 In [9]: pr = rc[:].apply_async(wait, 10)
249 292
250 293 # Poll to see if the result is ready
251 294 In [10]: pr.ready()
252 295 Out[10]: False
253 296
254 297 # ask for the result, but wait a maximum of 1 second:
255 298 In [45]: pr.get(1)
256 299 ---------------------------------------------------------------------------
257 300 TimeoutError Traceback (most recent call last)
258 301 /home/you/<ipython-input-45-7cd858bbb8e0> in <module>()
259 302 ----> 1 pr.get(1)
260 303
261 304 /path/to/site-packages/IPython/zmq/parallel/asyncresult.pyc in get(self, timeout)
262 305 62 raise self._exception
263 306 63 else:
264 307 ---> 64 raise error.TimeoutError("Result not ready.")
265 308 65
266 309 66 def ready(self):
267 310
268 311 TimeoutError: Result not ready.
269 312
270 313 .. Note::
271 314
272 315 Note the import inside the function. This is a common model, to ensure
273 316 that the appropriate modules are imported where the task is run.
274 317
275 318 Often, it is desirable to wait until a set of :class:`AsyncResult` objects
276 319 are done. For this, there is a the method :meth:`barrier`. This method takes a
277 320 tuple of :class:`AsyncResult` objects (or `msg_ids`) and blocks until all of the associated
278 321 results are ready:
279 322
280 323 .. sourcecode:: ipython
281 324
282 325 In [72]: rc.block=False
283 326
284 327 # A trivial list of AsyncResults objects
285 328 In [73]: pr_list = [rc[:].apply_async(wait, 3) for i in range(10)]
286 329
287 330 # Wait until all of them are done
288 331 In [74]: rc.barrier(pr_list)
289 332
290 333 # Then, their results are ready using get_result or the r attribute
291 334 In [75]: pr_list[0].get()
292 335 Out[75]: [2.9982571601867676, 2.9982588291168213, 2.9987530708312988, 2.9990990161895752]
293 336
294 337
295 338
296 339 The ``block`` and ``targets`` keyword arguments and attributes
297 340 --------------------------------------------------------------
298 341
299 342 .. warning::
300 343
301 344 This is different now, I haven't updated this section.
302 345 -MinRK
303 346
304 347 Most methods(like :meth:`apply`) accept
305 348 ``block`` and ``targets`` as keyword arguments. As we have seen above, these
306 349 keyword arguments control the blocking mode and which engines the command is
307 350 applied to. The :class:`Client` class also has :attr:`block` and
308 351 :attr:`targets` attributes that control the default behavior when the keyword
309 352 arguments are not provided. Thus the following logic is used for :attr:`block`
310 353 and :attr:`targets`:
311 354
312 355 * If no keyword argument is provided, the instance attributes are used.
313 356 * Keyword argument, if provided override the instance attributes.
314 357
315 358 The following examples demonstrate how to use the instance attributes:
316 359
317 360 .. sourcecode:: ipython
318 361
319 362 In [16]: rc.targets = [0,2]
320 363
321 364 In [17]: rc.block = False
322 365
323 366 In [18]: pr = rc.execute('a=5')
324 367
325 368 In [19]: pr.r
326 369 Out[19]:
327 370 <Results List>
328 371 [0] In [6]: a=5
329 372 [2] In [6]: a=5
330 373
331 374 # Note targets='all' means all engines
332 375 In [20]: rc.targets = 'all'
333 376
334 377 In [21]: rc.block = True
335 378
336 379 In [22]: rc.execute('b=10; print b')
337 380 Out[22]:
338 381 <Results List>
339 382 [0] In [7]: b=10; print b
340 383 [0] Out[7]: 10
341 384
342 385 [1] In [6]: b=10; print b
343 386 [1] Out[6]: 10
344 387
345 388 [2] In [7]: b=10; print b
346 389 [2] Out[7]: 10
347 390
348 391 [3] In [6]: b=10; print b
349 392 [3] Out[6]: 10
350 393
351 394 The :attr:`block` and :attr:`targets` instance attributes also determine the
352 395 behavior of the parallel magic commands.
353 396
354 397
355 398 Parallel magic commands
356 399 -----------------------
357 400
358 401 .. warning::
359 402
360 403 The magics have not been changed to work with the zeromq system. ``%px``
361 404 and ``%autopx`` do work, but ``%result`` does not. %px and %autopx *do
362 405 not* print stdin/out.
363 406
364 407 We provide a few IPython magic commands (``%px``, ``%autopx`` and ``%result``)
365 408 that make it more pleasant to execute Python commands on the engines
366 409 interactively. These are simply shortcuts to :meth:`execute` and
367 410 :meth:`get_result`. The ``%px`` magic executes a single Python command on the
368 411 engines specified by the :attr:`targets` attribute of the
369 412 :class:`MultiEngineClient` instance (by default this is ``'all'``):
370 413
371 414 .. sourcecode:: ipython
372 415
373 416 # Create a DirectView for all targets
374 417 In [22]: dv = rc[:]
375 418
376 419 # Make this DirectView active for parallel magic commands
377 420 In [23]: dv.activate()
378 421
379 422 In [24]: dv.block=True
380 423
381 424 In [25]: import numpy
382 425
383 426 In [26]: %px import numpy
384 427 Parallel execution on engines: [0, 1, 2, 3]
385 428 Out[26]:{0: None, 1: None, 2: None, 3: None}
386 429
387 430 In [27]: %px a = numpy.random.rand(2,2)
388 431 Parallel execution on engines: [0, 1, 2, 3]
389 432
390 433 In [28]: %px ev = numpy.linalg.eigvals(a)
391 434 Parallel execution on engines: [0, 1, 2, 3]
392 435
393 436 In [28]: dv['ev']
394 437 Out[44]: {0: array([ 1.09522024, -0.09645227]),
395 438 1: array([ 1.21435496, -0.35546712]),
396 439 2: array([ 0.72180653, 0.07133042]),
397 440 3: array([ 1.46384341e+00, 1.04353244e-04])}
398 441
399 442 .. Note::
400 443
401 444 ``%result`` doesn't work
402 445
403 446 The ``%result`` magic gets and prints the stdin/stdout/stderr of the last
404 447 command executed on each engine. It is simply a shortcut to the
405 448 :meth:`get_result` method:
406 449
407 450 .. sourcecode:: ipython
408 451
409 452 In [29]: %result
410 453 Out[29]:
411 454 <Results List>
412 455 [0] In [10]: print numpy.linalg.eigvals(a)
413 456 [0] Out[10]: [ 1.28167017 0.14197338]
414 457
415 458 [1] In [9]: print numpy.linalg.eigvals(a)
416 459 [1] Out[9]: [-0.14093616 1.27877273]
417 460
418 461 [2] In [10]: print numpy.linalg.eigvals(a)
419 462 [2] Out[10]: [-0.37023573 1.06779409]
420 463
421 464 [3] In [9]: print numpy.linalg.eigvals(a)
422 465 [3] Out[9]: [ 0.83664764 -0.25602658]
423 466
424 467 The ``%autopx`` magic switches to a mode where everything you type is executed
425 468 on the engines given by the :attr:`targets` attribute:
426 469
427 470 .. sourcecode:: ipython
428 471
429 472 In [30]: dv.block=False
430 473
431 474 In [31]: %autopx
432 475 Auto Parallel Enabled
433 476 Type %autopx to disable
434 477
435 478 In [32]: max_evals = []
436 479 <IPython.zmq.parallel.asyncresult.AsyncResult object at 0x17b8a70>
437 480
438 481 In [33]: for i in range(100):
439 482 ....: a = numpy.random.rand(10,10)
440 483 ....: a = a+a.transpose()
441 484 ....: evals = numpy.linalg.eigvals(a)
442 485 ....: max_evals.append(evals[0].real)
443 486 ....:
444 487 ....:
445 488 <IPython.zmq.parallel.asyncresult.AsyncResult object at 0x17af8f0>
446 489
447 490 In [34]: %autopx
448 491 Auto Parallel Disabled
449 492
450 493 In [35]: dv.block=True
451 494
452 495 In [36]: px ans= "Average max eigenvalue is: %f"%(sum(max_evals)/len(max_evals))
453 496 Parallel execution on engines: [0, 1, 2, 3]
454 497
455 498 In [37]: dv['ans']
456 499 Out[37]: {0 : 'Average max eigenvalue is: 10.1387247332',
457 500 1 : 'Average max eigenvalue is: 10.2076902286',
458 501 2 : 'Average max eigenvalue is: 10.1891484655',
459 502 3 : 'Average max eigenvalue is: 10.1158837784',}
460 503
461 504
462 505 .. Note::
463 506
464 507 Multiline ``%autpx`` gets fouled up by NameErrors, because IPython
465 508 currently introspects too much.
466 509
467 510
468 511 Moving Python objects around
469 512 ============================
470 513
471 514 In addition to calling functions and executing code on engines, you can
472 515 transfer Python objects to and from your IPython session and the engines. In
473 516 IPython, these operations are called :meth:`push` (sending an object to the
474 517 engines) and :meth:`pull` (getting an object from the engines).
475 518
476 519 Basic push and pull
477 520 -------------------
478 521
479 522 Here are some examples of how you use :meth:`push` and :meth:`pull`:
480 523
481 524 .. sourcecode:: ipython
482 525
483 526 In [38]: rc.push(dict(a=1.03234,b=3453))
484 527 Out[38]: {0: None, 1: None, 2: None, 3: None}
485 528
486 529 In [39]: rc.pull('a')
487 530 Out[39]: {0: 1.03234, 1: 1.03234, 2: 1.03234, 3: 1.03234}
488 531
489 532 In [40]: rc.pull('b',targets=0)
490 533 Out[40]: 3453
491 534
492 535 In [41]: rc.pull(('a','b'))
493 536 Out[41]: {0: [1.03234, 3453], 1: [1.03234, 3453], 2: [1.03234, 3453], 3:[1.03234, 3453]}
494 537
495 538 # zmq client does not have zip_pull
496 539 In [42]: rc.zip_pull(('a','b'))
497 540 Out[42]: [(1.03234, 1.03234, 1.03234, 1.03234), (3453, 3453, 3453, 3453)]
498 541
499 542 In [43]: rc.push(dict(c='speed'))
500 543 Out[43]: {0: None, 1: None, 2: None, 3: None}
501 544
502 545 In non-blocking mode :meth:`push` and :meth:`pull` also return
503 546 :class:`AsyncResult` objects:
504 547
505 548 .. sourcecode:: ipython
506 549
507 550 In [47]: rc.block=False
508 551
509 552 In [48]: pr = rc.pull('a')
510 553
511 554 In [49]: pr.get()
512 555 Out[49]: [1.03234, 1.03234, 1.03234, 1.03234]
513 556
514 557
515 558
516 559
517 560 Dictionary interface
518 561 --------------------
519 562
520 563 Since a namespace is just a :class:`dict`, :class:`DirectView` objects provide
521 564 dictionary-style access by key and methods such as :meth:`get` and
522 565 :meth:`update` for convenience. This make the remote namespaces of the engines
523 566 appear as a local dictionary. Underneath, this uses :meth:`push` and
524 567 :meth:`pull`:
525 568
526 569 .. sourcecode:: ipython
527 570
528 571 In [50]: rc.block=True
529 572
530 573 In [51]: rc[:]['a']=['foo','bar']
531 574
532 575 In [52]: rc[:]['a']
533 576 Out[52]: {0: ['foo', 'bar'], 1: ['foo', 'bar'], 2: ['foo', 'bar'], 3: ['foo', 'bar']}
534 577
535 578 Scatter and gather
536 579 ------------------
537 580
538 581 Sometimes it is useful to partition a sequence and push the partitions to
539 582 different engines. In MPI language, this is know as scatter/gather and we
540 583 follow that terminology. However, it is important to remember that in
541 584 IPython's :class:`Client` class, :meth:`scatter` is from the
542 585 interactive IPython session to the engines and :meth:`gather` is from the
543 586 engines back to the interactive IPython session. For scatter/gather operations
544 587 between engines, MPI should be used:
545 588
546 589 .. sourcecode:: ipython
547 590
548 591 In [58]: rc.scatter('a',range(16))
549 592 Out[58]: {0: None, 1: None, 2: None, 3: None}
550 593
551 594 In [59]: rc[:]['a']
552 595 Out[59]: {0: [0, 1, 2, 3],
553 596 1: [4, 5, 6, 7],
554 597 2: [8, 9, 10, 11],
555 598 3: [12, 13, 14, 15]}
556 599
557 600 In [60]: rc.gather('a')
558 601 Out[60]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
559 602
560 603 Other things to look at
561 604 =======================
562 605
563 606 How to do parallel list comprehensions
564 607 --------------------------------------
565 608
566 609 In many cases list comprehensions are nicer than using the map function. While
567 610 we don't have fully parallel list comprehensions, it is simple to get the
568 611 basic effect using :meth:`scatter` and :meth:`gather`:
569 612
570 613 .. sourcecode:: ipython
571 614
572 615 In [66]: rc.scatter('x',range(64))
573 616 Out[66]: {0: None, 1: None, 2: None, 3: None}
574 617
575 618 In [67]: px y = [i**10 for i in x]
576 619 Executing command on Controller
577 620 Out[67]:
578 621
579 622 In [68]: y = rc.gather('y')
580 623
581 624 In [69]: print y
582 625 [0, 1, 1024, 59049, 1048576, 9765625, 60466176, 282475249, 1073741824,...]
583 626
584 627 Parallel exceptions
585 628 -------------------
586 629
587 630 In the multiengine interface, parallel commands can raise Python exceptions,
588 631 just like serial commands. But, it is a little subtle, because a single
589 632 parallel command can actually raise multiple exceptions (one for each engine
590 633 the command was run on). To express this idea, the MultiEngine interface has a
591 634 :exc:`CompositeError` exception class that will be raised in most cases. The
592 635 :exc:`CompositeError` class is a special type of exception that wraps one or
593 636 more other types of exceptions. Here is how it works:
594 637
595 638 .. sourcecode:: ipython
596 639
597 640 In [76]: rc.block=True
598 641
599 642 In [77]: rc.execute('1/0')
600 643 ---------------------------------------------------------------------------
601 644 CompositeError Traceback (most recent call last)
602 645
603 646 /ipython1-client-r3021/docs/examples/<ipython console> in <module>()
604 647
605 648 /ipython1-client-r3021/ipython1/kernel/multiengineclient.pyc in execute(self, lines, targets, block)
606 649 432 targets, block = self._findTargetsAndBlock(targets, block)
607 650 433 result = blockingCallFromThread(self.smultiengine.execute, lines,
608 651 --> 434 targets=targets, block=block)
609 652 435 if block:
610 653 436 result = ResultList(result)
611 654
612 655 /ipython1-client-r3021/ipython1/kernel/twistedutil.pyc in blockingCallFromThread(f, *a, **kw)
613 656 72 result.raiseException()
614 657 73 except Exception, e:
615 658 ---> 74 raise e
616 659 75 return result
617 660 76
618 661
619 662 CompositeError: one or more exceptions from call to method: execute
620 663 [0:execute]: ZeroDivisionError: integer division or modulo by zero
621 664 [1:execute]: ZeroDivisionError: integer division or modulo by zero
622 665 [2:execute]: ZeroDivisionError: integer division or modulo by zero
623 666 [3:execute]: ZeroDivisionError: integer division or modulo by zero
624 667
625 668 Notice how the error message printed when :exc:`CompositeError` is raised has
626 669 information about the individual exceptions that were raised on each engine.
627 670 If you want, you can even raise one of these original exceptions:
628 671
629 672 .. sourcecode:: ipython
630 673
631 674 In [80]: try:
632 675 ....: rc.execute('1/0')
633 676 ....: except client.CompositeError, e:
634 677 ....: e.raise_exception()
635 678 ....:
636 679 ....:
637 680 ---------------------------------------------------------------------------
638 681 ZeroDivisionError Traceback (most recent call last)
639 682
640 683 /ipython1-client-r3021/docs/examples/<ipython console> in <module>()
641 684
642 685 /ipython1-client-r3021/ipython1/kernel/error.pyc in raise_exception(self, excid)
643 686 156 raise IndexError("an exception with index %i does not exist"%excid)
644 687 157 else:
645 688 --> 158 raise et, ev, etb
646 689 159
647 690 160 def collect_exceptions(rlist, method):
648 691
649 692 ZeroDivisionError: integer division or modulo by zero
650 693
651 694 If you are working in IPython, you can simple type ``%debug`` after one of
652 695 these :exc:`CompositeError` exceptions is raised, and inspect the exception
653 696 instance:
654 697
655 698 .. sourcecode:: ipython
656 699
657 700 In [81]: rc.execute('1/0')
658 701 ---------------------------------------------------------------------------
659 702 CompositeError Traceback (most recent call last)
660 703
661 704 /ipython1-client-r3021/docs/examples/<ipython console> in <module>()
662 705
663 706 /ipython1-client-r3021/ipython1/kernel/multiengineclient.pyc in execute(self, lines, targets, block)
664 707 432 targets, block = self._findTargetsAndBlock(targets, block)
665 708 433 result = blockingCallFromThread(self.smultiengine.execute, lines,
666 709 --> 434 targets=targets, block=block)
667 710 435 if block:
668 711 436 result = ResultList(result)
669 712
670 713 /ipython1-client-r3021/ipython1/kernel/twistedutil.pyc in blockingCallFromThread(f, *a, **kw)
671 714 72 result.raiseException()
672 715 73 except Exception, e:
673 716 ---> 74 raise e
674 717 75 return result
675 718 76
676 719
677 720 CompositeError: one or more exceptions from call to method: execute
678 721 [0:execute]: ZeroDivisionError: integer division or modulo by zero
679 722 [1:execute]: ZeroDivisionError: integer division or modulo by zero
680 723 [2:execute]: ZeroDivisionError: integer division or modulo by zero
681 724 [3:execute]: ZeroDivisionError: integer division or modulo by zero
682 725
683 726 In [82]: %debug
684 727 >
685 728
686 729 /ipython1-client-r3021/ipython1/kernel/twistedutil.py(74)blockingCallFromThread()
687 730 73 except Exception, e:
688 731 ---> 74 raise e
689 732 75 return result
690 733
691 734 # With the debugger running, e is the exceptions instance. We can tab complete
692 735 # on it and see the extra methods that are available.
693 736 ipdb> e.
694 737 e.__class__ e.__getitem__ e.__new__ e.__setstate__ e.args
695 738 e.__delattr__ e.__getslice__ e.__reduce__ e.__str__ e.elist
696 739 e.__dict__ e.__hash__ e.__reduce_ex__ e.__weakref__ e.message
697 740 e.__doc__ e.__init__ e.__repr__ e._get_engine_str e.print_tracebacks
698 741 e.__getattribute__ e.__module__ e.__setattr__ e._get_traceback e.raise_exception
699 742 ipdb> e.print_tracebacks()
700 743 [0:execute]:
701 744 ---------------------------------------------------------------------------
702 745 ZeroDivisionError Traceback (most recent call last)
703 746
704 747 /ipython1-client-r3021/docs/examples/<string> in <module>()
705 748
706 749 ZeroDivisionError: integer division or modulo by zero
707 750
708 751 [1:execute]:
709 752 ---------------------------------------------------------------------------
710 753 ZeroDivisionError Traceback (most recent call last)
711 754
712 755 /ipython1-client-r3021/docs/examples/<string> in <module>()
713 756
714 757 ZeroDivisionError: integer division or modulo by zero
715 758
716 759 [2:execute]:
717 760 ---------------------------------------------------------------------------
718 761 ZeroDivisionError Traceback (most recent call last)
719 762
720 763 /ipython1-client-r3021/docs/examples/<string> in <module>()
721 764
722 765 ZeroDivisionError: integer division or modulo by zero
723 766
724 767 [3:execute]:
725 768 ---------------------------------------------------------------------------
726 769 ZeroDivisionError Traceback (most recent call last)
727 770
728 771 /ipython1-client-r3021/docs/examples/<string> in <module>()
729 772
730 773 ZeroDivisionError: integer division or modulo by zero
731 774
732 775 .. note::
733 776
734 777 The above example appears to be broken right now because of a change in
735 778 how we are using Twisted.
736 779
737 780 All of this same error handling magic even works in non-blocking mode:
738 781
739 782 .. sourcecode:: ipython
740 783
741 784 In [83]: rc.block=False
742 785
743 786 In [84]: pr = rc.execute('1/0')
744 787
745 788 In [85]: pr.get()
746 789 ---------------------------------------------------------------------------
747 790 CompositeError Traceback (most recent call last)
748 791
749 792 /ipython1-client-r3021/docs/examples/<ipython console> in <module>()
750 793
751 794 /ipython1-client-r3021/ipython1/kernel/multiengineclient.pyc in _get_r(self)
752 795 170
753 796 171 def _get_r(self):
754 797 --> 172 return self.get_result(block=True)
755 798 173
756 799 174 r = property(_get_r)
757 800
758 801 /ipython1-client-r3021/ipython1/kernel/multiengineclient.pyc in get_result(self, default, block)
759 802 131 return self.result
760 803 132 try:
761 804 --> 133 result = self.client.get_pending_deferred(self.result_id, block)
762 805 134 except error.ResultNotCompleted:
763 806 135 return default
764 807
765 808 /ipython1-client-r3021/ipython1/kernel/multiengineclient.pyc in get_pending_deferred(self, deferredID, block)
766 809 385
767 810 386 def get_pending_deferred(self, deferredID, block):
768 811 --> 387 return blockingCallFromThread(self.smultiengine.get_pending_deferred, deferredID, block)
769 812 388
770 813 389 def barrier(self, pendingResults):
771 814
772 815 /ipython1-client-r3021/ipython1/kernel/twistedutil.pyc in blockingCallFromThread(f, *a, **kw)
773 816 72 result.raiseException()
774 817 73 except Exception, e:
775 818 ---> 74 raise e
776 819 75 return result
777 820 76
778 821
779 822 CompositeError: one or more exceptions from call to method: execute
780 823 [0:execute]: ZeroDivisionError: integer division or modulo by zero
781 824 [1:execute]: ZeroDivisionError: integer division or modulo by zero
782 825 [2:execute]: ZeroDivisionError: integer division or modulo by zero
783 826 [3:execute]: ZeroDivisionError: integer division or modulo by zero
784 827
785 828
General Comments 0
You need to be logged in to leave comments. Login now