Python 使用多处理存储大型图像

Python 使用多处理存储大型图像,python,multiprocessing,Python,Multiprocessing,我用PyQt5编写了一个应用程序/Gui,希望存储大图像(>5000 RGB图像) 现在,我有一个函数,它用cv2.imwrite存储每张图片,但是这个过程需要很多时间。我在Stackoverflow中读到,我可以通过多处理来实现这一点。但是我对python非常陌生 我的多处理代码: def SaveImages(self): jobs = [] for i in range(5): p = multiprocessing.Process(target = sel

我用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()
函数中的SaveAllImages是存储每帧图像的基本代码。如果我运行此代码-出现错误:

p = multiprocessing.Process(target = SaveAllImages, args=self)
NameError: name 'SaveAllImages' is not defined
但是SaveAllImages被定义为:def SaveAllImages(self)

因此,我的问题是:

  • 为什么我会犯这个错误

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


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

    您可能会看到多线程处理比多处理性能更好。多处理最适合于CPU限制的任务,原因很简单,Python对所有操作都使用全局锁。多处理是绕过这个锁的一种手段。使用它比使用线程更糟糕,除非绝对必要,否则最好避免使用它

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

    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
    。如果您还希望并行生成图像,那么这可能是值得的


    无论是
    ThreadPoolExecutor
    还是
    ProcessPoolExecutor
    更好,这在很大程度上取决于您剩余的工作负载是什么以及您如何构建它。两种方法都试一下,看看哪一种更适合你。请注意,多处理限制了工作人员之间的通信和共享状态,因此我建议首先尝试线程。

    在尝试改进之前,应始终衡量性能

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

    然后使用性能监视程序检查程序生成的写入吞吐量(无多线程/处理)。 如果您的程序大部分时间都能达到与测试程序相同的吞吐量,那么您所能做的就很少了


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

    您好,欢迎使用StackOverflow。请提供一个我们可以合作的解决方案,以便更好地了解您的问题。多处理更多的是用于处理而不是存储。。。你能退一步说一下你真正想要实现什么吗?你的任务是I/O限制的,而不是CPU限制的,因此它不太可能通过多处理得到改善。多处理还需要为每个新工作进程生成一个进程副本(在Windows上这很昂贵,因为Windows上的Python缺少fork实现),因此它可能弊大于利。显示的代码块与显示的错误不匹配-前者使用
    self.SaveAllImages
    ,后者只是
    保存所有图像
    。多线程主要是为了伪并行,而不是为了提高性能。在这里,多线程和多处理不太可能提高性能(这对于OP的需求至关重要),因为任务基本上是I/O绑定的。@AlexanderHuszagh多线程很可能在这里提高性能,正是因为OP的工作负载是I/O绑定的。这是Python中多线程的一个主要用例。I/O调用释放GIL。@AlexanderHuszagh如果这就是你的基准测试的样子,那么难怪你有错误的想法。8MB用于测试I/O?写同一个文件,使其进入操作系统缓存?然而,在我的机器上,并行版本仍然快25%?对于更大的缓冲区,速度是原来的两倍?@AlexanderHuszagh这不是为了复杂而复杂。OP正在尝试做5000件昂贵的事情。并行性肯定会帮助他们。他们正在努力使某些东西发挥作用。他们很可能会将整个操作并行化。如果你喜欢自己强烈的观点,那么就把你糟糕的态度放在自己的答案中。亚当,我从来没有写过平行度是“最差的”(而且,阿法尤),亚历山大也没有。但我认为,我们应该始终清楚地认识到,某些方法与另一种方法相比,是或可能是更好的,这不仅取决于我们的经验和常识,而且也要尊重我们可以对其他人的方法做出的假设。我们不知道他们的经验、背景和知识,也不知道硬件/软件后端或具体配置。因此,这两种理论都可能是正确的,但我认为我们应该澄清这两个方面/现实,以便OP和未来将面临类似问题的所有其他用户。