例子:
image = Image.open('foo.png')
# releases the GIL?
resized = image.resize((800, 600), Image.ANTIALIAS)
# reacquires the GIL?
很显然,变量赋值需要持有GIL,但将其拆分为两行比较困难。 :)
如果有两个线程在进行图像调整大小,这些调整大小能够在两个不同的核心上运行吗?
例子:
image = Image.open('foo.png')
# releases the GIL?
resized = image.resize((800, 600), Image.ANTIALIAS)
# reacquires the GIL?
很显然,变量赋值需要持有GIL,但将其拆分为两行比较困难。 :)
如果有两个线程在进行图像调整大小,这些调整大小能够在两个不同的核心上运行吗?
看源码1.1.7,似乎没有在_resize
中释放GIL。
释放GIL的函数似乎是:
PyImaging_CreateWindowWin32 (createwindow on Win32)
PyImaging_EventLoopWin32 (eventloop on Win32)
pyCMSdoTransform (apply)
_buildTransform (buildTransform)
_buildProofTransform (buildProofTransform)
_encode_to_file (encode_to_file)
请注意,潜在的阻塞或长时间运行的操作,例如I/O、图像处理和NumPy数值计算,发生在GIL之外。因此,只有在多线程程序中,花费大量时间在GIL内部解释CPython字节码时,GIL才会成为瓶颈。
PIL使用C扩展来完成大部分重活。因此,如果适用,实际的图像调整应该利用多线程。
如果您想同时调整多个图像,请考虑使用Python本地的multiprocessing库。这应该可以实现使用多个核心的期望效果。
PyEval_SaveThread()
调用来释放,该调用由ImagingSectionEnter()
调用,在数十个地方调用。因此,GIL似乎被相当积极地释放。(尽管在图像加载期间显然不是这样。) - Lawrence Kesteloot