当我的 Python 脚本生成一个线程并运行以下代码段时,运行时间为 0.8 秒。 当它生成五个线程并运行代码时,运行时间为 ~5.0 秒。
显然,我希望代码即使在 5 或 5 个线程中也能在 ~0.8 秒内运行。 为什么会这样? 我已经使用线程来改善程序其他部分的运行时间,但由于某种原因,它在这里成为瓶颈。 此外,我从未生成过超过 60 个线程,因此这不会影响性能。
# Open the image
imgx = Image.open(imgName)
imgx = imgx.convert("RGBA")
pix = imgx.load()
# Adjust dark pixels to black or white
for y in xrange(imgx.size[1]):
for x in xrange(imgx.size[0]):
# Get RGBA values for a pixel
(first, second, third, alpha) = pix[x, y]
# Ajust the RGBA values accordingly
if (first > threshold) or (second > threshold) or (third > threshold):
first = 255
second = 255
third = 255
alpha = 255
else:
first = 0
second = 0
third = 0
alpha = 255
# Set new pixel values
pix[x, y] = (first, second, third, alpha)
(称为全局解释器锁或 GIL),可防止纯 Python 代码在多个线程中并发运行。
无论如何,在 Python 循环中单独迭代像素是非常低效的。 您应该使用 Numpy 的矢量化函数,这些函数可以全局作用于数组。 这在单个线程中会快得多,并且具有额外的优势,即 Numpy 在数组操作期间释放 GIL,因此它们实际上可以在多个线程中并行发生。
您可能甚至不需要为此应用程序使用线程。 使用多个进程比使用线程处理的微妙之处要少得多。
Numpy 代码大致相当于您编写的代码
img = Image.open(imgName).convert("RGBA")
arr = numpy.array(img)
# Split the channels of the image by rotating the axes
r, g, b, a = arr.transpose(2, 0, 1)
# Create Boolean array: True means pixel is above threshold
bw = (r > threshold) | (g > threshold) | (b > threshold)
# Set R, G and B channel to the 255 times the B/W array
arr[:, :, :2] = 255 * bw[:, :, numpy.newaxis]
# Set alpha channel to 255
arr[:, :, 3] = 255
# Create new PIL image from array
new_img = Image.fromarray(arr)