I have a nested for loop in my python code that looks something like this:
results = []
for azimuth in azimuths:
for zenith in zeniths:
# Do various bits of stuff
# Eventually get a result
results.append(result)
I'd like to parallelise this loop on my 4 core machine to speed it up. Looking at the IPython parallel programming documentation (http://ipython.org/ipython-doc/dev/parallel/parallel_multiengine.html#quick-and-easy-parallelism) it seems that there is an easy way to use map
to parallelise iterative operations.
However, to do that I need to have the code inside the loop as a function (which is easy to do), and then map across this function. The problem I have is that I can't get an array to map this function across. itertools.product()
produces an iterator which I can't seem to use the map function with.
Am I barking up the wrong tree by trying to use map here? Is there a better way to do it? Or is there some way to use itertools.product
and then do parallel execution with a function mapped across the results?
I'm not really familiar with IPython, but an easy solution would seem to be to parallelize the outer loop only.
To parallelize every call, you just need to get a list for each argument. You can use
itertools.product
+zip
to get this:Then you can use map:
To go a bit deeper into the steps, here's an example:
So we have a "list of pairs", but what we really want is a single list for each argument, i.e. a "pair of lists". This is exactly what the slightly weird
zip(*product)
syntax gets us:Now we just map our function onto those two lists, to parallelize nested for loops:
And there's nothing special about there being only two - this method should extend to an arbitrary number of nested loops.
If you want to keep the structure of your loop, you can try using Ray (docs), which is a framework for writing parallel and distributed Python. The one requirement is that you would have to separate out the work that can be parallelized into its own function.
You can import Ray like this:
Then, your script would look like this:
I assume you are using IPython 0.11 or later. First of all define a simple function.
then use IPython's fine parallel suite to parallelize your problem. first start a controller with 5 engines attached (#CPUs + 1) by starting a cluster in a terminal window (if you installed IPython 0.11 or later this program should be present):
In your script connect to the controller and transmit all your tasks. The controller will take care of everything.
If you actually want to run your code in parallel, use
concurrent.futures