Это можно сделать элегантно с Ray , системой, которая позволяет вам легко распараллеливать и распространять ваш код Python.
Чтобы распараллелить ваш пример, вам нужно определить свои функции с помощью декоратора @ray.remote
, а затем вызвать их с помощью .remote
.
import numpy as np
import time
import ray
ray.init()
# Define the function. Each remote function will be executed
# in a separate process.
@ray.remote
def HeavyComputationThatIsThreadSafe(i, j):
n = i*j
time.sleep(0.5) # Simulate some heavy computation.
return n
N = 10
output_ids = []
for i in range(N):
for j in range(N):
# Remote functions return a future, i.e, an identifier to the
# result, rather than the result itself. This allows invoking
# the next remote function before the previous finished, which
# leads to the remote functions being executed in parallel.
output_ids.append(HeavyComputationThatIsThreadSafe.remote(i,j))
# Get results when ready.
output_list = ray.get(output_ids)
# Move results into an NxN numpy array.
outputs = np.array(output_list).reshape(N, N)
# This program should take approximately N*N*0.5s/p, where
# p is the number of cores on your machine, N*N
# is the number of times we invoke the remote function,
# and 0.5s is the time it takes to execute one instance
# of the remote function. For example, for two cores this
# program will take approximately 25sec.
Существует ряд преимуществ использования Ray по сравнению с многопроцессорным модулем . В частности, тот же код будет работать как на одной машине, так и на кластере машин. Для получения дополнительных преимуществ Рэй см. этот пост .
Примечание: Следует иметь в виду, что каждая удаленная функция выполняется в отдельном процессе, возможно, на другом компьютере, и поэтому вычисление удаленной функции должно занять больше, чем вызов удаленной функции. Как правило, вычисление удаленной функции должно занимать не менее нескольких 10 мсек, чтобы амортизировать затраты на планирование и запуск удаленной функции.