Show More
@@ -30,6 +30,9 b' class AsyncResult(object):' | |||||
30 |
|
30 | |||
31 | Provides the same interface as :py:class:`multiprocessing.AsyncResult`. |
|
31 | Provides the same interface as :py:class:`multiprocessing.AsyncResult`. | |
32 | """ |
|
32 | """ | |
|
33 | ||||
|
34 | msg_ids = None | |||
|
35 | ||||
33 | def __init__(self, client, msg_ids, fname=''): |
|
36 | def __init__(self, client, msg_ids, fname=''): | |
34 | self._client = client |
|
37 | self._client = client | |
35 | self.msg_ids = msg_ids |
|
38 | self.msg_ids = msg_ids |
@@ -455,8 +455,8 b' class Client(object):' | |||||
455 | md = {'msg_id' : parent['msg_id'], |
|
455 | md = {'msg_id' : parent['msg_id'], | |
456 | 'received' : datetime.now(), |
|
456 | 'received' : datetime.now(), | |
457 | 'engine_uuid' : header.get('engine', None), |
|
457 | 'engine_uuid' : header.get('engine', None), | |
458 |
'follow' : parent |
|
458 | 'follow' : parent.get('follow', []), | |
459 |
'after' : parent |
|
459 | 'after' : parent.get('after', []), | |
460 | 'status' : content['status'], |
|
460 | 'status' : content['status'], | |
461 | } |
|
461 | } | |
462 |
|
462 |
@@ -263,7 +263,7 b' class IPClusterApp(ApplicationWithClusterDir):' | |||||
263 | self.default_config.Global.engine_launcher = \ |
|
263 | self.default_config.Global.engine_launcher = \ | |
264 | 'IPython.zmq.parallel.launcher.LocalEngineSetLauncher' |
|
264 | 'IPython.zmq.parallel.launcher.LocalEngineSetLauncher' | |
265 | self.default_config.Global.n = 2 |
|
265 | self.default_config.Global.n = 2 | |
266 |
self.default_config.Global.delay = |
|
266 | self.default_config.Global.delay = 2 | |
267 | self.default_config.Global.reset_config = False |
|
267 | self.default_config.Global.reset_config = False | |
268 | self.default_config.Global.clean_logs = True |
|
268 | self.default_config.Global.clean_logs = True | |
269 | self.default_config.Global.signal = signal.SIGINT |
|
269 | self.default_config.Global.signal = signal.SIGINT |
@@ -53,7 +53,8 b' Architecture overview' | |||||
53 | The IPython architecture consists of four components: |
|
53 | The IPython architecture consists of four components: | |
54 |
|
54 | |||
55 | * The IPython engine. |
|
55 | * The IPython engine. | |
56 |
* The IPython |
|
56 | * The IPython hub. | |
|
57 | * The IPython schedulers. | |||
57 | * The controller client. |
|
58 | * The controller client. | |
58 |
|
59 | |||
59 | These components live in the :mod:`IPython.zmq.parallel` package and are |
|
60 | These components live in the :mod:`IPython.zmq.parallel` package and are | |
@@ -79,9 +80,9 b' to the user.' | |||||
79 | IPython controller |
|
80 | IPython controller | |
80 | ------------------ |
|
81 | ------------------ | |
81 |
|
82 | |||
82 |
The IPython controller provide |
|
83 | The IPython controller processes provide an interface for working with a set of engines. | |
83 |
general level, the controller is a collection of processes to which IPython engines |
|
84 | At a general level, the controller is a collection of processes to which IPython engines | |
84 | clients can connect. The controller is composed of a :class:`Hub` and a collection of |
|
85 | and clients can connect. The controller is composed of a :class:`Hub` and a collection of | |
85 | :class:`Schedulers`. These Schedulers are typically run in separate processes but on the |
|
86 | :class:`Schedulers`. These Schedulers are typically run in separate processes but on the | |
86 | same machine as the Hub, but can be run anywhere from local threads or on remote machines. |
|
87 | same machine as the Hub, but can be run anywhere from local threads or on remote machines. | |
87 |
|
88 | |||
@@ -92,8 +93,8 b" the client's :meth:`.Client.apply` method, with various arguments, or" | |||||
92 | constructing :class:`.View` objects to represent subsets of engines. The two |
|
93 | constructing :class:`.View` objects to represent subsets of engines. The two | |
93 | primary models for interacting with engines are: |
|
94 | primary models for interacting with engines are: | |
94 |
|
95 | |||
95 |
* A |
|
96 | * A **Direct** interface, where engines are addressed explicitly. | |
96 |
* A |
|
97 | * A **LoadBalanced** interface, where the Scheduler is trusted with assigning work to | |
97 | appropriate engines. |
|
98 | appropriate engines. | |
98 |
|
99 | |||
99 | Advanced users can readily extend the View models to enable other |
|
100 | Advanced users can readily extend the View models to enable other | |
@@ -108,7 +109,7 b' styles of parallelism.' | |||||
108 | The Hub |
|
109 | The Hub | |
109 | ******* |
|
110 | ******* | |
110 |
|
111 | |||
111 |
The center of an IPython cluster is the |
|
112 | The center of an IPython cluster is the Hub. This is the process that keeps | |
112 | track of engine connections, schedulers, clients, as well as all task requests and |
|
113 | track of engine connections, schedulers, clients, as well as all task requests and | |
113 | results. The primary role of the Hub is to facilitate queries of the cluster state, and |
|
114 | results. The primary role of the Hub is to facilitate queries of the cluster state, and | |
114 | minimize the necessary information required to establish the many connections involved in |
|
115 | minimize the necessary information required to establish the many connections involved in | |
@@ -138,16 +139,42 b' Security' | |||||
138 |
|
139 | |||
139 | IPython uses ZeroMQ for networking, which has provided many advantages, but |
|
140 | IPython uses ZeroMQ for networking, which has provided many advantages, but | |
140 | one of the setbacks is its utter lack of security [ZeroMQ]_. By default, no IPython |
|
141 | one of the setbacks is its utter lack of security [ZeroMQ]_. By default, no IPython | |
141 |
connections are |
|
142 | connections are encrypted, but open ports only listen on localhost. The only | |
142 | source of security for IPython is via ssh-tunnel. IPython supports both shell |
|
143 | source of security for IPython is via ssh-tunnel. IPython supports both shell | |
143 | (`openssh`) and `paramiko` based tunnels for connections. |
|
144 | (`openssh`) and `paramiko` based tunnels for connections. There is a key necessary | |
|
145 | to submit requests, but due to the lack of encryption, it does not provide | |||
|
146 | significant security if loopback traffic is compromised. | |||
144 |
|
147 | |||
145 | In our architecture, the controller is the only process that listens on |
|
148 | In our architecture, the controller is the only process that listens on | |
146 | network ports, and is thus the main point of vulnerability. The standard model |
|
149 | network ports, and is thus the main point of vulnerability. The standard model | |
147 | for secure connections is to designate that the controller listen on |
|
150 | for secure connections is to designate that the controller listen on | |
148 |
localhost, and use ssh-tunnels |
|
151 | localhost, and use ssh-tunnels to connect clients and/or | |
149 | engines. |
|
152 | engines. | |
150 |
|
153 | |||
|
154 | To connect and authenticate to the controller an engine or client needs | |||
|
155 | some information that the controller has stored in a JSON file. | |||
|
156 | Thus, the JSON files need to be copied to a location where | |||
|
157 | the clients and engines can find them. Typically, this is the | |||
|
158 | :file:`~/.ipython/clusterz_default/security` directory on the host where the | |||
|
159 | client/engine is running (which could be a different host than the controller). | |||
|
160 | Once the JSON files are copied over, everything should work fine. | |||
|
161 | ||||
|
162 | Currently, there are two JSON files that the controller creates: | |||
|
163 | ||||
|
164 | ipcontroller-engine.json | |||
|
165 | This JSON file has the information necessary for an engine to connect | |||
|
166 | to a controller. | |||
|
167 | ||||
|
168 | ipcontroller-client.json | |||
|
169 | The client's connection information. This may not differ from the engine's, | |||
|
170 | but since the controller may listen on different ports for clients and | |||
|
171 | engines, it is stored separately. | |||
|
172 | ||||
|
173 | More details of how these JSON files are used are given below. | |||
|
174 | ||||
|
175 | A detailed description of the security model and its implementation in IPython | |||
|
176 | can be found :ref:`here <parallelsecurity>`. | |||
|
177 | ||||
151 | .. warning:: |
|
178 | .. warning:: | |
152 |
|
179 | |||
153 | Even at its most secure, the Controller listens on ports on localhost, and |
|
180 | Even at its most secure, the Controller listens on ports on localhost, and | |
@@ -157,9 +184,6 b' engines.' | |||||
157 | Controller is insecure. There is no way around this with ZeroMQ. |
|
184 | Controller is insecure. There is no way around this with ZeroMQ. | |
158 |
|
185 | |||
159 |
|
186 | |||
160 | .. TODO: edit parallelsecurity |
|
|||
161 | A detailed description of the security model and its implementation in IPython |
|
|||
162 | can be found :ref:`here <parallelsecurity>`. |
|
|||
163 |
|
187 | |||
164 | Getting Started |
|
188 | Getting Started | |
165 | =============== |
|
189 | =============== | |
@@ -170,7 +194,7 b' simply start a controller and engines on a single host using the' | |||||
170 | :command:`ipclusterz` command. To start a controller and 4 engines on your |
|
194 | :command:`ipclusterz` command. To start a controller and 4 engines on your | |
171 | localhost, just do:: |
|
195 | localhost, just do:: | |
172 |
|
196 | |||
173 | $ ipclusterz -n 4 |
|
197 | $ ipclusterz start -n 4 | |
174 |
|
198 | |||
175 | More details about starting the IPython controller and engines can be found |
|
199 | More details about starting the IPython controller and engines can be found | |
176 | :ref:`here <parallel_process>` |
|
200 | :ref:`here <parallel_process>` | |
@@ -189,12 +213,21 b' everything is working correctly, try the following commands:' | |||||
189 | Out[4]: set([0, 1, 2, 3]) |
|
213 | Out[4]: set([0, 1, 2, 3]) | |
190 |
|
214 | |||
191 | In [5]: c.apply(lambda : "Hello, World", targets='all', block=True) |
|
215 | In [5]: c.apply(lambda : "Hello, World", targets='all', block=True) | |
192 |
Out[5]: |
|
216 | Out[5]: [ 'Hello, World', 'Hello, World', 'Hello, World', 'Hello, World' ] | |
193 | 'Hello, World'} |
|
217 | ||
|
218 | ||||
|
219 | When a client is created with no arguments, the client tries to find the corresponding | |||
|
220 | JSON file in the local `~/.ipython/clusterz_default/security` directory. If it finds it, | |||
|
221 | you are set. If you have put the JSON file in a different location or it has a different | |||
|
222 | name, create the client like this: | |||
|
223 | ||||
|
224 | .. sourcecode:: ipython | |||
|
225 | ||||
|
226 | In [2]: c = client.Client('/path/to/my/ipcontroller-client.json') | |||
194 |
|
227 | |||
195 | Remember, a client needs to be able to see the Hub. So if they |
|
228 | Remember, a client needs to be able to see the Hub's ports to connect. So if they are on a | |
196 |
|
|
229 | different machine, you may need to use an ssh server to tunnel access to that machine, | |
197 |
then you would connect to it with: |
|
230 | then you would connect to it with: | |
198 |
|
231 | |||
199 | .. sourcecode:: ipython |
|
232 | .. sourcecode:: ipython | |
200 |
|
233 | |||
@@ -203,8 +236,8 b' then you would connect to it with::' | |||||
203 | Where 'myhub.example.com' is the url or IP address of the machine on |
|
236 | Where 'myhub.example.com' is the url or IP address of the machine on | |
204 | which the Hub process is running. |
|
237 | which the Hub process is running. | |
205 |
|
238 | |||
206 |
You are now ready to learn more about the :ref:` |
|
239 | You are now ready to learn more about the :ref:`Direct | |
207 |
<parallelmultiengine>` and :ref:` |
|
240 | <parallelmultiengine>` and :ref:`LoadBalanced <paralleltask>` interfaces to the | |
208 | controller. |
|
241 | controller. | |
209 |
|
242 | |||
210 | .. [ZeroMQ] ZeroMQ. http://www.zeromq.org |
|
243 | .. [ZeroMQ] ZeroMQ. http://www.zeromq.org |
@@ -1,10 +1,10 b'' | |||||
1 | .. _parallelmultiengine: |
|
1 | .. _parallelmultiengine: | |
2 |
|
2 | |||
3 |
========================== |
|
3 | ========================== | |
4 |
IPython's |
|
4 | IPython's Direct interface | |
5 |
========================== |
|
5 | ========================== | |
6 |
|
6 | |||
7 | The 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 | |
@@ -19,7 +19,7 b' 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:`ipclusterz` command:: |
|
20 | the :command:`ipclusterz` command:: | |
21 |
|
21 | |||
22 | $ ipclusterz -n 4 |
|
22 | $ ipclusterz 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 <ip1par>` to using IPython for parallel computing. |
|
25 | our :ref:`introduction <ip1par>` to using IPython for parallel computing. | |
@@ -36,16 +36,17 b' module and then create a :class:`.Client` instance:' | |||||
36 |
|
36 | |||
37 | In [2]: rc = client.Client() |
|
37 | In [2]: rc = client.Client() | |
38 |
|
38 | |||
39 | This form assumes that the controller was started on localhost with default |
|
39 | This form assumes that the default connection information (stored in | |
40 | configuration. If not, the location of the controller must be given as an |
|
40 | :file:`ipcontroller-client.json` found in `~/.ipython/clusterz_default/security`) is | |
41 | argument to the constructor: |
|
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 |
|
43 | |||
43 | .. sourcecode:: ipython |
|
44 | .. sourcecode:: ipython | |
44 |
|
45 | |||
45 | # for a visible LAN controller listening on an external port: |
|
46 | # If you have copied the json connector file from the controller: | |
46 | In [2]: rc = client.Client('tcp://192.168.1.16:10101') |
|
47 | In [2]: rc = client.Client('/path/to/ipcontroller-client.json') | |
47 |
# for a remote controller at my.server.com |
|
48 | # for a remote controller at 10.0.1.5, visible from my.server.com: | |
48 | In [3]: rc = client.Client(sshserver='my.server.com') |
|
49 | In [3]: rc = client.Client('tcp://10.0.1.5:12345', sshserver='my.server.com') | |
49 |
|
50 | |||
50 |
|
51 | |||
51 | To make sure there are engines connected to the controller, use can get a list |
|
52 | To make sure there are engines connected to the controller, use can get a list | |
@@ -63,8 +64,8 b' Quick and easy parallelism' | |||||
63 |
|
64 | |||
64 | In many cases, you simply want to apply a Python function to a sequence of |
|
65 | In many cases, you simply want to apply a Python function to a sequence of | |
65 | objects, but *in parallel*. The client interface provides a simple way |
|
66 | objects, but *in parallel*. The client interface provides a simple way | |
66 |
of accomplishing this: us |
|
67 | of accomplishing this: using the builtin :func:`map` and the ``@remote`` | |
67 | function decorator. |
|
68 | function decorator, or the client's :meth:`map` method. | |
68 |
|
69 | |||
69 | Parallel map |
|
70 | Parallel map | |
70 | ------------ |
|
71 | ------------ | |
@@ -72,7 +73,7 b' Parallel map' | |||||
72 | Python's builtin :func:`map` functions allows a function to be applied to a |
|
73 | Python's builtin :func:`map` functions allows a function to be applied to a | |
73 | sequence element-by-element. This type of code is typically trivial to |
|
74 | 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, |
|
75 | 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 :m |
|
76 | you can just use the builtin :func:`map`, or a client's :meth:`map` method: | |
76 |
|
77 | |||
77 | .. sourcecode:: ipython |
|
78 | .. sourcecode:: ipython | |
78 |
|
79 | |||
@@ -179,7 +180,6 b' blocks until the engines are done executing the command:' | |||||
179 | In [2]: rc.block=True |
|
180 | In [2]: rc.block=True | |
180 | In [3]: dview = rc[:] # A DirectView of all engines |
|
181 | In [3]: dview = rc[:] # A DirectView of all engines | |
181 | In [4]: dview['a'] = 5 |
|
182 | In [4]: dview['a'] = 5 | |
182 |
|
||||
183 |
|
183 | |||
184 | In [5]: dview['b'] = 10 |
|
184 | In [5]: dview['b'] = 10 | |
185 |
|
185 |
@@ -24,7 +24,7 b' To follow along with this tutorial, you will need to start the IPython' | |||||
24 | controller and four IPython engines. The simplest way of doing this is to use |
|
24 | controller and four IPython engines. The simplest way of doing this is to use | |
25 | the :command:`ipclusterz` command:: |
|
25 | the :command:`ipclusterz` command:: | |
26 |
|
26 | |||
27 | $ ipclusterz -n 4 |
|
27 | $ ipclusterz start -n 4 | |
28 |
|
28 | |||
29 | For more detailed information about starting the controller and engines, see |
|
29 | For more detailed information about starting the controller and engines, see | |
30 | our :ref:`introduction <ip1par>` to using IPython for parallel computing. |
|
30 | our :ref:`introduction <ip1par>` to using IPython for parallel computing. |
General Comments 0
You need to be logged in to leave comments.
Login now