Parallelism in one line
medium.com
medium.com
So you can't use it in interactive sessions:
In [1]: import multiprocessing
In [2]: pool = multiprocessing.Pool(8)
In [3]: def hello(x):
....: return x+1
....:
In [5]: stuff = range(10)
In [4]: pool.map(hello, stuff)
# cryptic errors
You also can't use it with lambdas or functions defined within functions; suppose I put this in test.py: import multiprocessing
def run_stuff():
pool = multiprocessing.Pool(8)
def hello(x):
return x+1
stuff = range(10)
return pool.map(hello, stuff)
print(run_stuff())
... I get the same errors.This is sad because pool.map seems to be faster than anything I have written myself which might replace it without the above limitations. Unless someone out there has done better than me? :)
>>> import multiprocessing
>>> def hello(x):
... return x + 1
...
>>> pool = multiprocessing.Pool(8)
>>> pool.map(hello, range(10))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
It looks like the pool takes a peek at the module during instantiation. Maybe could be worked around by having a lazy pool that only inspects when you call map.If functions within functions are not supported I don't see the problem, because the thing with multiprocessing is that you need to be conscious of what you're passing between processes, so explicitly passing everything as arguments or through an initializer is the way to go.
Yeah, the requirement that things be picklable in order to send to another process is one of the worst parts of Python in my opinion. I can write the bulk of my code without running into the limitation, but when I do hit it? Holy crap. Rage.
The only work around I've found, which isn't really a work around at all, is throwing out the idea of small, side effect free functions. By which I mean, give the process everything it needs to get the resources on "its" side (thus avoiding the pickling), and then let it process stuff until it's gotten back to some serializable base object that it can finally return. Not ideal, but that's how I generally work around it.
There's also `multiprocessing.Array` and `Value` which avoid the pickle requirement completely, as they're shared memory, but limit you to very base datatypes. Really only good if your operating on some homogeneous array (which for me isn't too often).
from gevent import monkey
monkey.patch_all()
This is a lot lighter than processes. You can combine the two- use gevent to handle network, and then multiprocessing to handle cpu stuff!The only thing about gevent is that the docs kind of suck, but their apis are pretty intuitive and the code itself is well documented.
In the last example:
pool = Pool()
pool.map(create_thumbnail, images)
pool.close()
pool.join()
would be 2 fewer lines with concurrent.futures: with ThreadPoolExecutor(max_workers=4) as executor:
executor.map(create_thumbnail, images)
[1] https://pay.reddit.com/r/Python/comments/1tyzw3/parallelism_... from multiprocessing import Pool
from contextlib import closing
with closing(Pool(15)) as p
p.map(f, myiterable)
takes <30 sec vs from concurrent.futures import ThreadPoolExecutor as Pool
with Pool(15) as p
p.map(f, myiterable)
that takes > 1min.whereas ProcessPoolExecutor hangs, and I've no clue why.
Stop. Let me reformulate. If you follow the standard AJAX route and return either a {'success': True, 'payload': ...} or {'success': False, 'error': ...} from your workers, your error handling will be fine.
When you think about more details, you grow more and more sophisticated solution that best suits your needs. But the point of the post is different: it's a dead simple way to start. Starting is often the hardest part.
I think it's clear that these sorts of details belong in the library. Everybody could hack together their own traceback collector, segfault handlers etc., but it's difficult to get right and in a scripting language you should be able to forget about such things.
edit: I guess I didn't really answer the segfault issue. Beyond checking the return code of the child process to see if it segfault'ed (so you can log it or retry it) I'm not sure of how you could get more informative failing info.
http://www.reddit.com/r/Python/comments/1w6h6g/parallelism_i...
List<String> contents = Arrays.stream(urls).parallel().map(UrlLoader::getContent).collect(Collectors.toList());
but as far as I know the API doesn't provide any way to get a String from an URL, so you need an helper class that also workaround checked exceptions ... public class UrlLoader {
private static String getContent(String url) {
try {
return new BufferedReader(new InputStreamReader(new URL(url).openConnection().getInputStream())).lines().collect(Collectors.joining("\n"));
} catch (IOException e) {
throw new IOError(e);
}
}
}
so not a real one liner :(In addition, it looks like you are unfairly picking on Java. The producer consumer model presented isn't anywhere near what a competent programmer would do. Building your consumer from within a method called Producer? Calling isinstance (or instanceof) to check if the "poison pill" is put in the queue? These are the signs of a crappy programmer, not a crappy language.
Secondly, I wasn't really "picking" on Java. A one line comment about Java liking classes is pretty far from being "unfair," me thinks. Again, in the context of the article, I was simply (attempting (though may have failed)) to use it as a (hopefully mild-chuckle worthy) example of the different ways things can be done in a language.
Finally, I'm not entirely sure why your complaining about stripped down example code... It's example code, man.
http://docs.julialang.org/en/latest/manual/parallel-computin...
1) Put the addresses of your remote workers (via ssh) in a file, and point Julia at the file.
2) Julia connects to remote workers on each host.
3) Use one of the convenient macros or functions to run the code (this evenly distributes a map reduce to throw 200 million coins and count heads). > nheads = @parallel (+) for i=1:200000000 > int(randbool()) > end
4) You can also do all of the pool stuff, manual message passing, etc, if you need to.
But yeah, multiprocessing.Pool.map,imap, imap_unordered are neat.
In the words of a great man, it's a jolly hard problem.