我想在Python中使用多个线程来计算图像的像素值,最后要构建它,尽管我很难弄清楚如何获取线程的结果并收集它。这是设置:
创建了一个Queue.Queue()
对象,以及一个threading.Thread()
类子:
q = Queue.Queue()
class myThread(threading.Thread):
def __init__(self, queue):
self.queue = queue
threading.Thread.__init__(self)
def run(self):
while True: # loop forever
task = self.queue.get()
rs = self.do_work(task) # I've got the result; now what to do with it?
self.queue.task_done()
我的想法是收集500x500图像的像素数据,这个图像最初是250,000(500x500)个元素的列表,最终将用PIL制作成图像:
pixels = array.array('B', pixels).tostring()
im = Image.fromstring('L', size, pixels)
im.show()
所以我用每个像素的任务填充队列,并产生一个线程池:
for i in range(5):
t = myThread(q)
t.setDaemon(True)
t.start()
for y in range(500):
for x in range(500):
q.put({'x':x, 'y':y})
q.join()
那么如何获取所有数据呢?我认为将250,000个元素列表传递给每个线程都是一个坏主意,两者都是为了传递的数据数组的大小,并且因为每个线程都会丢失来自其他线程的数据。
修改 对于那些想知道以多线程方式完成这项工作是否值得的人来说,计算图像坐标所做的工作是几个perlin噪声函数。它正在生成一个perlin 2D噪声点阵列(一个5x5网格),加上几个八度音程(10x10,20x20和40x40网格),并计算这些点之间的像素值。因此,对于最终图像中的每个像素,它必须每个八度音程执行三次数学运算(给定点周围的平均X点,给定点周围的平均Y点,并平均这些平均值),然后在八度音结果之间进行加权平均。
在我的8核Mac上,我看到Python进程在运行时使用1个线程和100%的处理器。虽然我知道我有8个内核并且已经看到进程显示400-600%的处理器使用以显示它们正在利用其他内核,我只是希望这个Python脚本可以做同样的事情。
答案 0 :(得分:2)
Python有一个用于修改python级数据结构的全局锁,称为GIL。这使得很难有效地完成你想用线程做的事情。
但是,绝望不是!那种开发人员给了我们多处理模块。用多处理替换线程(使用multiprocessing.Process和multiprocessing.Queue代替),瞧,你的应用程序是一个多进程应用程序。
至于你的问题,你想要另一个队列,朝另一个方向走。
答案 1 :(得分:1)
我认为你应该使用两个队列。
一个用于工作/任务,一个用于输出。
任务完成后,将结果放在输出队列中。
答案 2 :(得分:0)
我会有一个可以被每个线程访问的全局列表。我实际上有这样的情况并且没有问题就这样做了。