Python中的多处理 - 并发

时间:2014-01-08 10:51:17

标签: python multiprocessing multicore

我有一个简单的类ImageData,使用Shepard插值创建一些图像。我必须生成超过50个图像,所以我可以并行化这个。我试过这个(我之前从未使用过多处理,所以,对不起,如果我做了些蠢事),已经应用了@Alfe教给我的东西:

class ImageData(object):

    def __init__(self, width, height, range_min=-1, range_max=1):
        """
        The ImageData constructor
        """
        self.width = width
        self.height = height
        #The values range each pixel can assume
        self.range_min = range_min
        self.range_max = range_max
        self.data = []
        for i in range(width):
            self.data.append([0] * height)

    def shepard_interpolation(self, queue, seeds=10):
        """
        Perform a Shepard shepard_interpolation
        :param queue
        :param seeds
        """
        points = []
        f = []
        for s in range(seeds):
            # Generate a pixel position
            pos_x = random.randrange(self.width)
            pos_y = random.randrange(self.height)

            # Save the f(x,y) data
            x = Utils.translate_range(pos_x, 0, self.width, self.range_min, self.range_max)
            y = Utils.translate_range(pos_y, 0, self.height, self.range_min, self.range_max)
            z = Utils.function(x, y)
            points.append([x, y])
            f.append(z)

        for i in range(self.width):
            xt = (Utils.translate_range(i, 0, self.width, self.range_min, self.range_max))
            for j in range(self.height):
                yt = (Utils.translate_range(j, 0, self.height, self.range_min, self.range_max))
                self.data[i][j] = Utils.shepard_euclidian(points, f, [xt, yt], 3)
        queue.put(self)


if __name__ == '__main__':
    q = Queue()
    processes = [Process(target=ImageData.shepard_interpolation, args=(ImageData(50, 50), q,))    for _ in range(2)]
    for process in processes:
        process.start()
    for process in processes:
        process.join()

    print "Finish"

问题是'因为当我调用传球范围(2)时,一切正常,但是当我尝试使用范围(3)时,它永远不会结束(我的代码永远不会达到'完成'打印)并且我不知道为什么。而且,在我的情况下,我必须生成超过50个图像,我不知道如何实现这一点。我有一个处理器Core 2 Duo。

编辑:

我试图评论queue.put(self)并且它有效。但是我必须收到结果,这是迄今为止我知道的唯一方法来实现这一目标。我也不明白为什么它有两个进程。 关于我能做些什么来解决这个问题的任何想法?我猜错误是在shepard_euclidian方法中。但直到现在我才找到它。这是这个功能:

def shepard_euclidian(x, z, p, u):
    n = len(x)
    d = [0.0] * n
    for i in range(n-1):
        pi = x[i]
        d[i] = math.pow(math.hypot(pi[0]-p[0], pi[1]-p[1]), u)
    w = [0.0] * n
    sw = 0.0
    for i in range(n-1):
        w[i] = 1.0
        for k in range(n-1):
            if i != k:
                w[i] *= d[k]
        sw += w[i]
    for i in range(len(w)-1):
        if sw != 0.0:
            w[i] /= sw
        else:
            w[i] = 0.0
    c = 0.0
    for i in range(n):
        c += (w[i] * z[i])
    return c

当我尝试这个时:

for i in range(self.width):
        xt = (Uts.Utils.translate_range(i, 0, self.width, self.range_min, self.range_max))
        for j in range(self.height):
            yt = (Uts.Utils.translate_range(j, 0, self.height, self.range_min, self.range_max))
            data = Uts.Utils.shepard_euclidian(points, f, [xt, yt], 3)
    queue.put(data)

有效。但这不是我想要的。

如果我试试这个:

   aux = ImageData(50, 50)
   for i in range(self.width):
        xt = (Uts.Utils.translate_range(i, 0, self.width, self.range_min, self.range_max))
        for j in range(self.height):
            yt = (Uts.Utils.translate_range(j, 0, self.height, self.range_min, self.range_max))
            aux[x][y] = Uts.Utils.shepard_euclidian(points, f, [xt, yt], 3)
   self.data = aux
   queue.put(self.data)

它不起作用。我真的不知道该怎么做。

任何帮助将不胜感激。 提前谢谢。

1 个答案:

答案 0 :(得分:1)

您想要记住所有进程(在您的外观中称为k丑陋)并在第二个循环中加入所有。也许这解决了你手头的问题。

请使用更好的名字:

processes = [
  Process(target=ImageData.shepard_interpolation, args=(ImageData(50, 50), q,))
  for _ in range(3) ]
for process in processes:
    process.start()
for process in processes:
    process.join()

编辑:

我的代码的最小版本在我的机器上没有问题:

import os
from multiprocessing import *

class ImageData(object):
    def __init__(self, a, b):
        pass

    def shepard_interpolation(self, queue, seeds=10):
        self.pid = os.getpid()
        print self.pid, "queue put"
        queue.put(self)

if __name__ == '__main__':
    q = Queue()
    processes = [ Process(
      target=ImageData.shepard_interpolation, args=(ImageData(50, 50), q))
        for _ in range(10) ]
    for process in processes:
        process.start()
    results = []
    for process in processes:  # just to have the correct amount of results
        results.append(q.get())
    print '---------Out--------'
    for process in processes:
        process.join()
    print [ result.pid for result in results ]