我在调用OpenCV函数的循环中运行了一个cpu密集型任务。我试图使用多进程并行化任务,但是并行化代码比串行代码运行得慢。我尝试了以下几点:
def compute_homographies(present_objects, best_homographies):
t1 = time.time()
# The homographies dictionary is passed to the worker function and
# is a shared dictionary created using multiprocessing.Manager()
# After the workers finish, it should contain the best
# homography for each of the present objects.
homographies = manager.dict()
pool = multiprocessing.Pool(processes=4)
for source, target in present_objects:
# get the best homography computed so far for this object
best_homography = best_homographies[source.name]
pool.apply_async(find_best_homographies,
(source, target, homographies, best_homography, ))
pool.close()
pool.join()
print("Computing homographies took ", time.time() - t1)
best_homographies.update(homographies)
return homographies
def find_best_homographies(source, target, homographies, best_homography):
t1 = time.time()
#CPU intensive task, involving calling OpenCV
homography = compute_homography(source, target)
# checking if the computed homography is better
# than the best_homography. CPU intensive task
# involves calling OpenCV.
if is_better(homography, best_homography):
homographies[source.name] = homography
else:
homographies[source.name] = best_homography
print("Finding homograpy for {} took {}".format(source.name, time.time() - t1))如果我在没有多处理的情况下运行这段代码,find_best_homographies函数将花费大约50到80毫秒的时间,而所有对象的计算大约需要“单独调用find_best_homographies的总和”。如果我运行上述代码,首先对find_best_homographies的每次调用所需的时间几乎是以前的两倍,对所有对象的总调用甚至比单个调用的总和还要长两倍。我预计,在平行情况下的总时间将是个人通话的最大时间。
source和target是简单类的实例。它们都包含一个Numpy数组,用于保存大小约为300×300像素的RGB图像。
这里出什么问题了?如何才能获得比串行案例更好的性能?
我也尝试使用进程并行化,但结果是一样的。
发布于 2018-10-16 12:33:16
这是个疯狂的猜测..。通常,当CPU密集型工作在使用进程并行时减慢时,造成这种情况的原因是进程之间的数据传输。如果你在你的进程中调用一个函数,传递它的参数并返回一些东西,数据就会被“传输”到这个函数中,然后通过在内存中复制对象或者只是传递一个不可变的引用指针来将数据“传输”到这个函数中。如果将参数传递给池工作人员并返回结果,则在实际使用队列时会发生这种情况。这比在内存中复制要慢得多.
在您的例子中,您还拥有Manager.dict()对象,这意味着使用队列进行更多的数据传输。
并行化版本的逻辑也有一些不太正确的地方(可能)。您使用apply_async(),它将任务传递给池,但不需要等待任务完成就立即返回。您的主程序进展到for循环的下一次迭代时,并不表示结果已经就绪。在apply_async中有一个回调功能,可以在结果可用时执行一些操作。如果你想评估
best_homography = best_homographies[source.name]在完成每个工作任务之后,在您编写的程序中不会发生这种情况。如果您的工作人员需要一些时间来完成,那么for循环将在单个工作人员的一小部分时间内完成,然后您的程序在join()中等待所有工作人员完成,这意味着在没有一个工作人员向字典提交结果的情况下,对该行的计算次数与您的present_objects中有元素的次数一样多。
https://stackoverflow.com/questions/52831261
复制相似问题