为什么在 Python 中使用多处理时数组不通过引用传递?
Why are arrays not passed by reference when using Multiprocessing in Python?
基本上,在下面的示例中,我想用列表中每个元素的位置填充一个五元素列表。我正在使用多处理来做到这一点。所以我希望即使每次填充列表的迭代可能不会按照更直观的顺序(从第一个元素到最后一个元素)发生,最终列表仍然会被正确填充。这依赖于 arr 通过引用传递的假设,因此实际上可以在每次调用函数 f 时进行更改。然而,arr 永远不会改变,当我们打印出来时,它仍然是它初始化的样子,即 [0]*5 = [0,0,0,0,0].
from joblib import Parallel, delayed
import multiprocessing
arr = [0]*5
cases = [0,1,2,3,4]
def f(arr, position):
arr[position] = position
num_cores = multiprocessing.cpu_count()
Parallel(n_jobs=num_cores)(delayed(f)(arr, position) for position in cases)
print arr
当我们不使用多处理时,我们得到预期的结果:
def f(arr, position):
arr[position] = position
arr = [0]*5
for i, el in enumerate(arr):
f(arr, i)
print arr
为什么会发生这种情况,即为什么在使用多处理时列表不通过引用传递?
如果您只想填充列表,那么您应该尝试使用 multiprocessing.Pool.map
。 map
的唯一问题是它在返回之前等待所有任务完成。因此,您可能希望探索 imap
替代方案。可能每个任务花费的时间都大不相同。在这种情况下,请查看 imap_unordered
(其中我还包含了一个示例)。
例如
from multiprocessing import Pool
from contextlib import closing
def f(n):
return n * 2
def g(args):
id_, n = args
return id_, -n
if __name__ == "__main__":
cases = range(5)
# Pool automatically uses the same number of subprocesses as cpu_count
with closing(Pool()) as pool:
arr = pool.map(f, cases)
print(arr) # prints [0, 2, 4, 6, 8]
arr = [None] * len(cases)
with closing(Pool()) as pool:
for idx, result in pool.imap_unordered(g, enumerate(cases)):
arr[idx] = result
print(arr) # prints [0, -1, -2, -3, -4]
基本上,在下面的示例中,我想用列表中每个元素的位置填充一个五元素列表。我正在使用多处理来做到这一点。所以我希望即使每次填充列表的迭代可能不会按照更直观的顺序(从第一个元素到最后一个元素)发生,最终列表仍然会被正确填充。这依赖于 arr 通过引用传递的假设,因此实际上可以在每次调用函数 f 时进行更改。然而,arr 永远不会改变,当我们打印出来时,它仍然是它初始化的样子,即 [0]*5 = [0,0,0,0,0].
from joblib import Parallel, delayed
import multiprocessing
arr = [0]*5
cases = [0,1,2,3,4]
def f(arr, position):
arr[position] = position
num_cores = multiprocessing.cpu_count()
Parallel(n_jobs=num_cores)(delayed(f)(arr, position) for position in cases)
print arr
当我们不使用多处理时,我们得到预期的结果:
def f(arr, position):
arr[position] = position
arr = [0]*5
for i, el in enumerate(arr):
f(arr, i)
print arr
为什么会发生这种情况,即为什么在使用多处理时列表不通过引用传递?
如果您只想填充列表,那么您应该尝试使用 multiprocessing.Pool.map
。 map
的唯一问题是它在返回之前等待所有任务完成。因此,您可能希望探索 imap
替代方案。可能每个任务花费的时间都大不相同。在这种情况下,请查看 imap_unordered
(其中我还包含了一个示例)。
例如
from multiprocessing import Pool
from contextlib import closing
def f(n):
return n * 2
def g(args):
id_, n = args
return id_, -n
if __name__ == "__main__":
cases = range(5)
# Pool automatically uses the same number of subprocesses as cpu_count
with closing(Pool()) as pool:
arr = pool.map(f, cases)
print(arr) # prints [0, 2, 4, 6, 8]
arr = [None] * len(cases)
with closing(Pool()) as pool:
for idx, result in pool.imap_unordered(g, enumerate(cases)):
arr[idx] = result
print(arr) # prints [0, -1, -2, -3, -4]