python - 主模块外的 Python 多处理:计算速度慢
问题描述
我有一个代码,旨在在不是 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
我检查了串行版本和并行版本都给出了相同的结果,除了串行版本比多处理版本快得多。在我的真实代码中,有时会出现这种情况,进入工作函数的“args”元组实际上包含一个大对象数据容器,其中包含一个更大的字典,用于从中读取数据以执行操作。谁能解释为什么我会观察到这种行为(即多处理时性能缓慢)?每次都需要将数据传递给工作函数,实际上这使得工作函数需要很多参数,这可能是导致 IPC 占用位置的代码变慢的原因?(¿?)
使用传递给工作人员的参数中的“重复”,因为元组传递的所有参数对于每个工作人员都必须相同,唯一可迭代的是列表“a”。有谁知道如何对此进行有效的多处理?另外,请注意,多处理不会发生在“main.py”级别,而是发生在代码逻辑中某些模块的“深层”函数中。我会很感激这里的一些帮助,以更好地了解这种多处理是如何工作的!我在 Windows 操作系统下使用 4 核机器,我现在知道 Windows 在使用多处理时不支持类似“fork”的行为。但是,在我的机器上运行 Ubuntu 中的代码似乎也很慢!谢谢!!
解决方案
我对当前代码的最佳猜测:您没有做足够的工作pool_worker_function
来抵消通信/同步的成本。
我可能错了,但是您的代码似乎完成了一半:chunks
从未使用过该变量。无论如何,传递一个大数组(你的块)可能不是最好的解决方案。
您可以尝试将 start/len 参数传递给您的pool_worker_function
,然后创建数组并在那里进行计算,但我不能 100% 确定它是否足以抵消结果的通信成本。
推荐阅读
- machine-learning - 为什么顺序特征选择器不会删除 STD=0 的特征
- javascript - JavaScript - 如何使用 reduce 将名称列表映射到指定键
- flutter - 从 initState 导航返回“findAncestorStateOfType”在 null 上调用
- makefile - 如何在Android make文件中将变量与值进行比较
- c++ - 如何使用 gsl 窄投
- git - 使用 Notepad++ diff 工具进行 git
- php - OpenSSL [des-ede3-cbc] 加密 php IV
- python - 并行运行
- angular - 如何停止加载器/微调器,直到所有http响应都以角度完成
- laravel - 为什么 Model mutators 不处理在数据库中播种一个类?(我错过了什么)