Create our Client

In [1]:

```
from IPython import parallel
client = parallel.Client()
lbv = client.load_balanced_view()
dview = client[:]
dview
```

Out[1]:

Interactively defined classes can be annoying to use with IPython.parallel. This stems from how class instances are serialized by pickle

In [2]:

```
# the real model object is much more involved...
class MyModel(object):
def maximize(self, r):
return max(r, 4)
def evaluate(r, model):
return model.maximize(r)
```

In [3]:

```
import cPickle as pickle
m = MyModel()
print pickle.dumps(m)
```

Note how the pickled model is almost nothing but a reference to `__main__.MyModel`

and `object`

.
This is how the instance will be reconstructed remotely. But the probem is that MyModel is not defined on the engines:

In [4]:

```
model = MyModel()
lbv.apply_sync(evaluate, 2, model)
```

This is a common problem with relying on interactively defined names, but there are issues peculiar to classes, as opposed to locally defined functions.

In IPython 0.13, there are a few shortcomings:

- Classes cannot be pushed, unlike functions.
- There is no way to use
`%%px`

to define a class*both*locally and remotely.

So defining a class everywhere is a two-step process, either manual:

In [19]:

```
class MyModel1(object):
def maximize(self, r):
return max(r, 0)
```

In [20]:

```
%%px
class MyModel1(object):
def maximize(self, r):
return max(r, 0)
```

In [21]:

```
model = MyModel1()
lbv.apply_sync(evaluate, 1, model)
```

Out[21]:

Or more automatic:

In [22]:

```
class MyModel2(object):
def maximize(self, r):
return max(r, 2)
```

In [23]:

```
# this just executes the previous cell on all our engines
# (note that In[-1] is *this* cell, so In[-2] is the previous one)
dview.execute(In[-2], block=True)
```

Out[23]:

In [24]:

```
model = MyModel2()
lbv.apply_sync(evaluate, 1, model)
```

Out[24]:

In IPython 1.0, this has been alleviated to some degree, by making interactively defined classes pushable,
and adding `%%px --local`

.

So now, you can use the same push step that is commonly used when you have multi-function tasks:

In [25]:

```
class MyModel3(object):
def maximize(self, r):
return max(r, 3)
```

In [26]:

```
dview['MyModel3'] = MyModel3
```

In [27]:

```
model = MyModel3()
lbv.apply_sync(evaluate, 0, model)
```

Out[27]:

Or you can simultaneously define the class both locally and remotely with `%%px --local`

In [28]:

```
%%px --local
# the real model object is much more involved...
class MyModel4(object):
def maximize(self, r):
return max(r, 4)
```

In [29]:

```
model = MyModel4()
lbv.apply_sync(evaluate, 2, model)
```

Out[29]:

Now, if you really want bleeding edge, there is an outstanding Pull Request that lets you define dependencies for locally defined names, which will actually attach the local objects to the task, so they are guaranteed to be defined when the task runs

In [30]:

```
class MyModel5(object):
def maximize(self, r):
return max(r, 5)
```

In [31]:

```
@parallel.require(MyModel5)
def evaluate(r, model):
return model.maximize(r)
```

In [32]:

```
model = MyModel5()
lbv.apply_sync(evaluate, 2, model)
```

Out[32]: