Going Parallel with concurrent.futures¶
Parallel computation can be implemented via the concurrent.futures module. The module is part of the standard library since Python 3.2
.
Let's look at a simple example.
from time import sleep
def slow_function(x):
print('start: {}'.format(x))
sleep(5)
print('done: {}'.format(x))
return x**2
We defined slow_function
, a function simulating a heavy computation (taking 5 seconds). We now run it in the most straightforward way.
numbers = range(4)
for n in numbers:
slow_function(n)
So, the functions are done one at a time as expected. Let's measure how long this take.
import time
numbers = range(4)
start_time = time.time()
for n in numbers:
slow_function(n)
print(time.time() - start_time, 'seconds')
It takes 20
seconds to run 4
functions. The reason is they are all run on one single core. Now, we refactor the execution, and we make it parallel.
from concurrent.futures import ProcessPoolExecutor
with ProcessPoolExecutor() as executor:
for n in numbers:
f = executor.submit(slow_function, n)
I am running these lines on a dual-core laptop. You can see that, indeed, the two cores are used simultaneously. The first two iterations are launched at the same time. Now, how much time do you expect we saved?
start_time = time.time()
with ProcessPoolExecutor() as executor:
for n in numbers:
f = executor.submit(slow_function, n)
print(time.time() - start_time, 'seconds')
Nice, the run-time was halved. It makes sense as we splitted the computation across two cores.