Quelle est la façon la plus simple de paralléliser ce code?
J'aime beaucoup concurrent.futures
pour cela, disponible en Python3 depuis la version 3.2 - et via backport vers 2.6 et 2.7 sur PyPi .
Vous pouvez utiliser des threads ou des processus et utiliser exactement la même interface.
Multiprocessing
Mettez ceci dans un fichier - futuretest.py:
import concurrent.futures
import time, random # add some random sleep time
offset = 2 # you don't supply these so
def calc_stuff(parameter=None): # these are examples.
sleep_time = random.choice([0, 1, 2, 3, 4, 5])
time.sleep(sleep_time)
return parameter / 2, sleep_time, parameter * parameter
def procedure(j): # just factoring out the
parameter = j * offset # procedure
# call the calculation
return calc_stuff(parameter=parameter)
def main():
output1 = list()
output2 = list()
output3 = list()
start = time.time() # let's see how long this takes
# we can swap out ProcessPoolExecutor for ThreadPoolExecutor
with concurrent.futures.ProcessPoolExecutor() as executor:
for out1, out2, out3 in executor.map(procedure, range(0, 10)):
# put results into correct output list
output1.append(out1)
output2.append(out2)
output3.append(out3)
finish = time.time()
# these kinds of format strings are only available on Python 3.6:
# time to upgrade!
print(f'original inputs: {repr(output1)}')
print(f'total time to execute {sum(output2)} = sum({repr(output2)})')
print(f'time saved by parallelizing: {sum(output2) - (finish-start)}')
print(f'returned in order given: {repr(output3)}')
if __name__ == '__main__':
main()
Et voici la sortie:
$ python3 -m futuretest
original inputs: [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
total time to execute 33 = sum([0, 3, 3, 4, 3, 5, 1, 5, 5, 4])
time saved by parallellizing: 27.68999981880188
returned in order given: [0, 4, 16, 36, 64, 100, 144, 196, 256, 324]
Multithreading
Maintenant , changez ProcessPoolExecutor
à ThreadPoolExecutor
, et exécutez à nouveau le module:
$ python3 -m futuretest
original inputs: [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
total time to execute 19 = sum([0, 2, 3, 5, 2, 0, 0, 3, 3, 1])
time saved by parallellizing: 13.992000102996826
returned in order given: [0, 4, 16, 36, 64, 100, 144, 196, 256, 324]
Vous avez maintenant effectué à la fois le multithreading et le multitraitement!
Remarque sur les performances et l'utilisation des deux ensemble.
L'échantillonnage est beaucoup trop petit pour comparer les résultats.
Cependant, je soupçonne que le multithreading sera plus rapide que le multitraitement en général, en particulier sous Windows, car Windows ne prend pas en charge le forking, donc chaque nouveau processus doit prendre du temps pour se lancer. Sur Linux ou Mac, ils seront probablement plus proches.
Vous pouvez imbriquer plusieurs threads dans plusieurs processus, mais il est recommandé de ne pas utiliser plusieurs threads pour dériver plusieurs processus.
calc_stuff
?