我试图理解多处理如何与Python一起工作。这是我的测试代码:
import numpy as np
import multiprocessing
import time
def worker(a):
for i in range(len(a)):
for j in arr2:
a[i] = a[i]*j
return len(a)
arr2 = np.random.rand(10000).tolist()
if __name__ == '__main__':
multiprocessing.freeze_support()
cores = multiprocessing.cpu_count()
arr1 = np.random.rand(1000000).tolist()
tmp = time.time()
pool = multiprocessing.Pool(processes=cores)
result = pool.map(worker, [arr1], chunksize=1000000/(cores-1))
print "mp time", time.time()-tmp
我有8个核心。它通常最终只有大约一秒使用〜3%的CPU的7个进程,最后一个进程永远使用~1 / 8的CPU ...(它已经运行了大约15分钟)
据我所知,进程间通信通常会限制并行编程的复杂性,但它通常需要这么长时间吗?还有什么可能导致最后一个过程永远消失?
这个帖子:Python multiprocessing never joins似乎解决了类似的问题,但它没有解决Pool的问题。
答案 0 :(得分:1)
看起来你想把工作分成几块。您可以使用范围功能对数据进行分区。在Linux上,分叉进程获得父内存的写时复制视图,因此您可以传递您想要处理的索引。在Windows上,没有这样的运气。您需要传入每个子列表。这个程序应该这样做
import numpy as np
import multiprocessing
import time
import platform
def worker(a):
if platform.system() == "Linux":
# on linux we passed in start:len
start, length = a
a = arr1[start:length]
for i in range(len(a)):
for j in arr2:
a[i] = a[i]*j
return len(a)
arr2 = np.random.rand(10000).tolist()
if __name__ == '__main__':
multiprocessing.freeze_support()
cores = multiprocessing.cpu_count()
arr1 = np.random.rand(1000000).tolist()
tmp = time.time()
pool = multiprocessing.Pool(processes=cores)
chunk = (len(arr1)+cores-1)//cores
# on Windows, pass the sublist, on linux just the indexes and let the
# worker split from the view of parent memory space
if platform.system() == "Linux":
seq = [(i, i+chunk) for i in range(0, len(arr1), chunk)]
else:
seq = [arr1[i:i+chunk] for i in range(0, len(arr1), chunk)]
result = pool.map(worker, seq, chunksize=1)
print "mp time", time.time()-tmp
答案 1 :(得分:0)
你指的是:
pool.map
将自动迭代程序中[arr1]
的对象。请注意,对象为[arr1]
但不是arr1
,这意味着您传递给pool.map
的对象的长度仅为一个。
我认为最简单的解决方案是将[arr1]
替换为arr1
。