[英]Python multiprocessing outside main module: slow computations
我有一个代码,旨在在不是 main.py 的某个模块的某个内部部分进行多处理。 为简单起见,我创建了一个包含两个文件的副本代码:main.py 和文件 f1_mod.py。 我的 main.py 看起来像:
import os
from time import time
import f1_mod
parallel = 1
N = 10000000
if __name__ == '__main__':
if not parallel:
time_start = time()
res = f1_mod.normal_exec( N )
time_end = time()
print("-->time is ", time_end - time_start )
else:
time_start = time()
res = f1_mod.parallel_exec( N )
time_end = time()
print("-->time is ", time_end - time_start )
for j in range( 100 ):
print( res[j] )
else:
print("--> CHILD PROCESS ID: ", os.getpid() )
pass
f1_mod.py 将是:
import multiprocessing as mp
import numpy as np
def pool_worker_function( k, args ):
d = args[0]
return d["p"]*( k**2 ) + d["x"]**2
def single_thread_exec( N ):
a = list( np.linspace( 0, N, N ) )
d = { "p": 0.2, "x": 0.5 }
result = []
for k in a:
result.append( d["p"]*( k**2) + d["x"]**2 )
return result
def parallel_exec( N ):
number_processors = mp.cpu_count()
number_used_processors = number_processors - 1
#try pool map method
from itertools import repeat
pool = mp.Pool( processes = number_used_processors )
d = { "p": 0.2, "x": 0.5 }
a = list( np.linspace( 0, N, N ) )
args = ( d, )
number_tasks = number_used_processors
chuncks = []
n_chunck = int( ( len(a) - 1 )/number_tasks )
for j in range( 0, number_tasks ):
if ( j == number_tasks - 1 ):
chuncks.append( a[ j*n_chunck: ] )
else:
chuncks.append( a[ j*n_chunck: j*n_chunck + n_chunck ] )
result = pool.starmap( pool_worker_function, zip( a, repeat( args ) ) )
pool.close()
pool.join()
return result
我检查了串行版本和并行版本都给出了相同的结果,除了串行版本比多处理版本快得多。 在我的真实代码中,有时会出现这种情况,进入 worker function 的“args”元组实际上包含一个大的 object 数据容器,其中包含一个更大的字典,用于从中读取数据以执行操作。 谁能解释为什么我会观察到这种行为(即多处理时性能缓慢)? 每次都需要将数据传递给工作人员 function ,实际上这使得工作人员 function 占用了大量 arguments 可能是什么减缓了 IPC 代码给出的地方? (¿?)
使用传递给工作人员的参数中的“重复”,因为元组传递的所有 arguments 对于每个工作人员都必须相同,唯一可迭代的是列表“a”。 有谁知道如何对此进行有效的多处理? 另外,请注意,多处理不会发生在“main.py”级别,而是发生在代码逻辑中某些模块的“深层”函数中。 我希望能得到一些帮助,以更好地理解这种多处理是如何工作的,我在 Windows 操作系统下使用 4 核机器。 我现在知道 Windows 在使用多处理时不支持类似“fork”的行为,但是,在我的机器上运行 Ubuntu 中的代码似乎也很慢! 谢谢!!
我对当前代码的最佳猜测:您在pool_worker_function
中没有做足够的工作来抵消通信/同步的成本。
我可能错了,但是您的代码似乎完成了一半:从未使用过chunks
变量。 无论如何,传递一个大的 arrays (你的块)可能不是最好的解决方案。
您可以尝试将 start/len 参数传递给您的pool_worker_function
,然后创建数组并在那里进行计算,但我不能 100% 确定它是否足以抵消结果的通信成本。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.