使用多处理来存储大图像



我在 PyQt5 中编写了一个应用程序/GUI,并希望存储大型图像(>5000 RGB 图像)

现在,我有一个函数,它使用cv2.imwrite存储每张图片,但这个过程需要很多时间。所以我在Stackoverflow中读到,我可以通过多处理来做到这一点。但我对python很陌生。

我的多处理代码:

def SaveImages(self):
jobs = []
for i in range(5):
p = multiprocessing.Process(target = self.SaveAllImages, args=self)
jobs.append(p)
p.start()

在函数中,保存所有图像是存储每帧图像的基本代码。如果我运行此代码 - 有一个错误:

p = multiprocessing.Process(target = SaveAllImages, args=self)
NameError: name 'SaveAllImages' is not defined

但是SaveAllImages是定义的:def SaveAllImages(self)

所以我的问题是:

  1. 为什么我变成了这个错误

  2. 如何实现非常简单的多处理来存储图像

您看到的错误是因为您调用的方法不存在,可能是因为它不是self的一部分。

您可能会看到多线程比多处理更好的性能。多处理最适合 CPU 密集型任务,原因很简单,Python 对所有操作都使用全局锁。多处理是绕过此锁的黑客。它比线程更讨厌,除非绝对必要,否则最好避免使用它。

线程对于您的用例来说可能已经足够了,它不会为新程序员带来很多陷阱。下面是一个使用 Python 3 的 Futures API 的工作示例设置,可以轻松扩展您的问题大小,只需在标记的位置添加您的参数和实际保存代码即可。

import concurrent.futures
# Save single image
def save_image(image_arg):
# your image save code goes here
print("Working on image {}...".format(image_arg))
return True
# max_workers specifies the number of threads. If None then use 5x your CPU count
with concurrent.futures.ThreadPoolExecutor(max_workers=None) as executor:
# Images we'll save. Depending on how you generate your images you might not
# want to materialize a list like this to avoid running out of memory.
image_args = ["image1", "image2", "image3"]
# Submit futures to the executor pool.
# Map each future back to the arguments used to create that future. That way
# if one fails we know which image it was that failed.
future_to_args = {executor.submit(save_image, image_arg): image_arg for image_arg in image_args}
# Images are being saved in worker threads. They will complete in any order.
for future in concurrent.futures.as_completed(future_to_args):
image_arg = future_to_args[future]
try:
result = future.result()
except Exception as exc:
print("Saving image {} generated an exception: {}".format(image_arg, exc))
else:
print("Image {} saved successfully.".format(image_arg))

如果您坚持使用多处理,只需使用ProcessPoolExecutor即可。如果您还想并行生成图像,这可能是值得的。

ThreadPoolExecutorProcessPoolExecutor更好在很大程度上取决于其余工作负载是什么以及您如何构建它。尝试两者,看看哪个更适合您。请注意,多处理对工作线程之间的通信和共享状态施加了限制,因此我建议先尝试线程。

在尝试改进之前,您应该始终衡量绩效。

使用磁盘测试程序查看磁盘的最大持续写入吞吐量是多少。

然后使用性能监视程序检查程序生成的写入吞吐量(无多线程/处理)。 如果您的程序在大多数时候可以达到与测试程序相同的吞吐量,那么您几乎无能为力。

假设您使用的是普通硬盘,则提高写入性能的最佳方法是改用 SSD。

相关内容

  • 没有找到相关文章

最新更新