Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python—多处理会降低性能_Python_Opencv_Multiprocessing - Fatal编程技术网

Python—多处理会降低性能

Python—多处理会降低性能,python,opencv,multiprocessing,Python,Opencv,Multiprocessing,我有一个cpu密集型任务运行在一个调用OpenCV函数的循环中。 我尝试使用多处理来并行化任务,但是并行化的代码比串行代码运行得慢。 我尝试了以下方法: def compute_同音词(呈现对象、最佳同音词): t1=时间。时间() #同音字字典被传递给worker函数并 #是使用multiprocessing.Manager()创建的共享字典 #工人完成后,应包含最好的 #每个当前对象的单应性。 同音字=manager.dict() 池=多处理。池(进程=4) 对于当前对象中的源、目标: #获

我有一个cpu密集型任务运行在一个调用OpenCV函数的循环中。 我尝试使用多处理来并行化任务,但是并行化的代码比串行代码运行得慢。 我尝试了以下方法:

def compute_同音词(呈现对象、最佳同音词):
t1=时间。时间()
#同音字字典被传递给worker函数并
#是使用multiprocessing.Manager()创建的共享字典
#工人完成后,应包含最好的
#每个当前对象的单应性。
同音字=manager.dict()
池=多处理。池(进程=4)
对于当前对象中的源、目标:
#获取迄今为止为此对象计算的最佳单应性
best_homography=best_homographies[source.name]
pool.apply\u async(查找\u最佳\u同音词,
(源、目标、同形字、最佳同形字)
pool.close()
pool.join()
打印(“计算同音字所花费的时间”,time.time()-t1)
最佳谐音。更新(谐音)
返回同音字
def查找最佳同形文字(源、目标、同形文字、最佳同形文字):
t1=时间。时间()
#CPU密集型任务,包括调用OpenCV
单应性=计算单应性(源、目标)
#检查计算的单应性是否更好
#比最好的单应性。CPU密集型任务
#涉及调用OpenCV。
如果更好(单应性,最佳单应性):
同形字[source.name]=同形字
其他:
同形字[source.name]=最佳同形字
print(“查找{}的同形文字采用{}”。格式(source.name,time.time()-t1))
如果我在不进行多处理的情况下运行此代码,
find_best_homographies
函数大约需要50到80毫秒,所有对象的计算大约需要“对
find_best_homographies
的单个调用之和”。 如果我运行上述代码,首先对
find\u best\u homographies
的每次调用几乎需要两倍的时间,而对所有对象的总调用甚至比单个调用的总和还要长两倍。我希望并行情况下的总时间是单个调用的最大时间

目标
是简单类的实例。它们都包含一个Numpy阵列,用于保存大小约为300x300像素的RGB图像

这里出了什么问题?如何实现比串行情况更好的性能


我还尝试使用进程进行并行化,但结果是一样的

这是一个疯狂的猜测。。。通常,当使用进程进行并行化时,CPU密集型工作速度减慢时,原因是进程之间的数据传输。如果在进程内调用函数,传输它的参数并返回某些内容,则数据通过在内存中复制对象或传递引用指针(如果不可变)来“传输”到函数中或从函数中传出。若您将参数传递给池工作者并返回结果,则在实际使用队列时会发生这种情况。这比在内存中复制要慢得多

在您的例子中,还有
Manager.dict()
对象,这意味着使用队列进行更多的数据传输

并行版本的逻辑也有一些不太正确的地方(可能)。您可以使用
apply\u async()
,它将任务传递给池,但会立即返回,而无需等待任务完成。主程序进入for循环的下一个迭代并不表示结果已准备就绪。apply_async中有一个回调功能,可以在结果可用时执行某些操作。如果你希望评估

best_homography = best_homographies[source.name]

完成每个辅助任务后,您编写的程序中不会发生这种情况。如果您的辅助进程需要一些时间才能完成,则for循环只需单个辅助进程的一小部分时间即可完成,然后您的程序将在
join()
中等待所有辅助进程完成,这意味着这一行的计算次数与
present\u对象中的元素的计算次数相同,而没有一个工作人员将其结果提交给字典

将磁盘平行放置通常是个坏主意。如果你的内存计算足够快,那么这样做确实会使你的性能比串行的差。这在很大程度上取决于函数在做什么。这是一个更适合代码审查的问题,如果您需要代码优化方面的帮助,您应该提供完整的代码(带有可以运行的示例)。尽管如此,您确实没有足够的有意义的代码来告诉您为什么会发生这种情况。没有看到一个最小的例子,我没有任何东西可以看或玩。谢谢你的评论。我从代码中删除了磁盘访问(读写)。性能有所提高。但我仍然看到相同的奇怪模式:在串行情况下,函数调用占用的时间更少,总时间是单个函数调用的总和。在并行情况下,函数调用需要更长的时间,并且总和比单个调用的总和高出两到三倍。我相应地编辑了这个问题。欢迎来到并行化和减速的奇妙世界。在池的进程之间传递对象会带来一定的开销。创建和处理池本身也需要很多时间。我用一个非常小的worker方法进行测试。在我的计算机中,仅创建池、执行async_调用、关闭池和连接需要150到200毫秒。关于逻辑,我认为没有问题。我希望并行计算不同物理对象的同音字,然后返回所有对象的字典。因此,我必须等待所有对象的结果被计算出来。