在Python中使用多线程来更快地处理图像?

4
在一个Python + Python Image Library脚本中,有一个名为processPixel(image, pos)的函数,它根据图像和其上的位置计算出一个数学索引。使用一个简单的for循环,对每个像素计算出该索引:
for x in range(image.size[0)):
    for y in range(image.size[1)):
        myIndex[x,y] = processPixel(image,[x,y])

这需要太多时间。如何实现线程以分割工作并加速它?多线程代码可以更快吗?具体而言,这是否由处理器核心数量定义?

1
此外,我非常愿意打赌 processPixel 可以进行 "numpy-化",这样你会看到比当前方法更快的速度提升。 - Joe Kington
3个回答

7

由于全局解释器锁(GIL)的原因,无法使用线程来加速。Python解释器的某些内部状态受到该锁的保护,这阻止了需要修改该状态的不同线程同时运行。

您可以通过使用multiprocessing来生成实际进程来加快速度。每个进程将在其自己的解释器中运行,从而绕过线程的限制。使用多处理,您可以使用共享内存,或为每个进程提供其自己的数据副本/分区。

根据您的任务,您可以通过分区将单个图像的处理并行化,也可以通过并行处理图像列表(后者可以使用轻松完成)。如果要使用前者,您可能需要将图像存储在可以作为共享内存访问的数组中,但仍然必须解决写入结果的位置问题(写入共享内存可能会严重影响性能)。还要注意,某些进程之间的通信方式(队列、管道或模块中某些函数的参数/返回值传递)需要使用Pickle对数据进行序列化。这会对数据施加一定的限制,并可能造成显着的性能开销(特别是如果您有许多小任务)。
另一种提高此类操作性能的方法是尝试使用Cython编写它们,该语言具有自己的OpenMP并行化支持-虽然我从未使用过,所以不知道它可以提供多少帮助。

如果你正在处理图像(或者进行任何需要大量计算能力的操作),那么你也应该考虑使用GPU。Python肯定支持它。 - freakish
正如@freakish所建议的那样,你应该使用基于GPU的解决方案来解决这种问题。你关于GIL和多进程的说法是正确的,但对于图像处理仍然没有帮助。当涉及到数组处理时,我建议使用NumPy,因为它专门设计用于高效的数组处理。 - aculich

1

以下是一些库列表,您可以探索以进行高效的图像处理:

OpenCV - 是一个编程函数库,用于实时计算机视觉和图像处理,包含Python绑定。

PyOpenCL 允许您从Python访问GPU和其他大规模并行计算设备。

PyCUDAPyOpenCL的姊妹项目。

NumPy和SciPy 是进行科学计算的基本软件包,可帮助上述软件包进行高效的图像和数组处理。

另外请注意,对于图像处理,一些人建议使用的多进程库并不能有效地帮助您处理图像处理,因此您应该避免使用操作系统线程来进行此操作。如果出于某种原因您确实需要粗粒度并行性,则可以使用MPI Python库,但您可能希望坚持使用基于GPU的库

1

教程中的链接失效了 - Monica Heddneck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接