[IPython-User] parallel question
MinRK
benjaminrk@gmail....
Mon Jan 2 17:46:01 CST 2012
On Mon, Jan 2, 2012 at 11:11, Toby Burnett <tburnett@uw.edu> wrote:
> Oops: that lambda function does not work with a global variable, my
> specific use case. :-(
>
> This is what does work instead:
>
> @interactive
> def remotefun(f,x):
> return eval(f,globals())(x)
>
> --Toby Burnett
>
> From: Toby Burnett
> Sent: Monday, January 02, 2012 09:12
> To: 'MinRK'
> Cc: ipython-user@scipy.org
> Subject: RE: [IPython-User] parallel question
>
> I’ve used MinRK’s solution for a while, but wanted to encapsulate the
> scheme into a class that manages a set of engines, and avoid ‘wiring in’
> the function name in code. The tricky thing is to avoid closure, which
> prevents the necessary use of pickle.
> Here is what works, for comments and suggestions.
>
> def submit(self, code, *pars):
> """ submit jobs to the engines
> code : string that must evaluate to a function to be executed on
> the target machine
> pars : one or more lists of arguments for the function
> """
> print ’submitting %d tasks '%len(pars[0])
> retun self.lview.map( lambda f,x: eval(f)(x), len(pars[0])*[code],
> *pars))
>
>
> The inelegant feature is duplication of the string defining the function.
>
> --Toby Burnett
>
You might try using the Reference object, for reconstructing remote objects
by name:
from IPython.parallel import Reference
rf = Reference(fname)
# workaround for bug soon to be fixed, preventing References from being
used in map:
rf.__name__ = fname
amr = self.lview.map(rf, *pars)
You can use References to objects by name, so that you can call functions
with arguments without transferring them (See
here<http://minrk.github.com/scipy-tutorial-2011/basic_remote.html?highlight=reference#working-with-the-engine-namespace>
for
some more info). I had never thought of using References for the callable
itself, but there's no reason not to support it.
Ideally, map should be able to take a Reference as the callable, but
there's a small bug where it is assumed that the function passed to apply
has a `__name__` attribute. I'll do a PR removing this assumption shortly,
but for now, simply setting the __name__ attribute should allow you to use
this.
This means that you should be able to change your code to:
def submit(self, f, *pars):
if isinstance(f, basestring):
name = f
f = Reference(name)
f.__name__ = name # workaround
print ’submitting %d tasks '%len(pars[0])
return self.lview.map(f, *pars)
Which should accept *both* locally defined functions and ones that exist
only remotely if given by name.
-MinRK
> From: MinRK [mailto:benjaminrk@gmail.com]
> Sent: Tuesday, December 27, 2011 22:28
> To: Toby Burnett
> Cc: ipython-user@scipy.org
> Subject: Re: [IPython-User] parallel question
>
>
> On Tue, Dec 27, 2011 at 12:36, Toby Burnett <tburnett@uw.edu> wrote:
> Hi,
> With the old MultiEngineClient, I used to set up local objects in the
> individual engines, say a function ‘f’, and then invoke them by name. An
> equivalent thing now is
> dview.map_sync(lambda x: eval(‘f’)(x), range(100))
>
> This line works fine, if f is defined as a function on the engines, only
> if I type it on the command line. If the lambda function is precompiled
> code however, I get error messages from the clients about ‘f’ not being
> defined, e.g.
> [0:apply]: NameError: name 'f' is not defined
>
> This has me very puzzled, I presume related to how the communication from
> the controller to the engines works?
>
> The lambda in question is defined in a module? If so, then the issue is
> that the globals() of the lambda is that of its module, instead of the
> user_ns (`__main__` on the engine). If we didn't do this, calling apply
> with library functions (e.g. os.getpid, or numpy.linalg.norm) would not
> work. If you are defining a function specifically for interactive use,
> IPython provides a `@interactive` decorator, which makes the function
> behave remotely as if it was defined interactively (when reconstructed on
> the engines, it is constructed with user_ns as globals(), instead of the
> module in which it was defined):
>
> #mymodule
> from IPython.parallel.util import interactive
>
> @interactive
> def foo(x):
> return eval('f')(x)
> # can also be just:
> # return f(x)
> # as long as there is no `f` defined in the current scope, causing a
> closure to be detected.
>
> ...
>
> In [20]: dview['f'] = lambda x: x*x
> In [21]: dview.map_sync(mymodule.foo, range(100))
>
>
> -MinRK
>
>
>
> --Toby Burnett
>
> _______________________________________________
> IPython-User mailing list
> IPython-User@scipy.org
> http://mail.scipy.org/mailman/listinfo/ipython-user
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.scipy.org/pipermail/ipython-user/attachments/20120102/eceefcdf/attachment.html
More information about the IPython-User
mailing list