【问题标题】:Good example implementation of multiprocessing?多处理的好示例实现?
【发布时间】:2015-10-29 10:08:25
【问题描述】:

我正在尝试将我的一个程序转换为使用多处理,最好是多处理池,因为这些看起来更简单。在高层次上,该过程是从图像中创建一组补丁,然后将它们传递给 GPU 以进行对象检测。 CPU和GPU部分各需要4s左右,但是CPU有8个核心,它不需要等待GPU,因为数据经过GPU后没有进一步的操作。

这是我想象的应该如何工作的图表:

为了帮助这个过程,我想要一个我的实现的高级版本的演示。假设我们正在遍历一个包含 10 个图像的文件夹中的图像列表。我们一次调整 4 张图像的大小。然后我们一次将它们转换为黑白两个,我们可以将转换作为GPU处理的一部分。下面是代码的样子:

def im_resize(im, num1, num2):
    return im.resize((num1, num2), Image.ANTIALIAS)

def convert_bw(im):
    return im.convert('L')

def read_images(path):
    imlist = []
    for pathAndFileName in glob.iglob(os.path.join(path, "*")):
        if pathAndFileName.endswith(tuple([".jpg", ".JPG"])):
            imlist.append(Image.open(pathAndFileName))
    return imlist


img_list = read_images("path/to/images/")
final_img_list = []

for image in img_list:

    # Resize needs to run concurrently on 4 processes so that the next img_tmp is always ready to go for convert
    img_tmp = im_resize(image, 100, 100)

    # Convert is limited, need to run on 2 processes
    img_tmp = convert_bw(img_tmp)
    final_img_list.append(img_tmp)

特定数量的进程等原因是由于系统性能指标,这将减少运行时间。我只是想确保 GPU 不必等待 CPU 完成处理图像,并且我希望有一个充满预处理图像的恒定队列,以供 GPU 运行。我希望在大约 4-10 个预处理图像的队列中保持最大大小。如果你们可以帮助我说明我将如何通过这个简化的示例来实现这一点,我相信我可以弄清楚如何将它翻译成我需要的。

谢谢!

【问题讨论】:

  • 那里有很多例子。你看过doc page吗?它说明了几种情况。您基本上希望每个阶段都有一个单独的池,您希望使用限制数量的工人进行农场锻炼。考虑一下您将对输入数据集合应用什么功能转换以获取输出集合,然后不要使用map 应用它,而是使用Pool.map 应用它。然后,您可以使用getjoin 将数据尽可能晚地编组回主进程。
  • 我看过这些,但由于 python 都是顺序的,我觉得它们并没有完全说明进程是如何工作的,以及 .join() 究竟如何控制它们的执行。在我看来, .join 似乎完全停止了执行。该信息对于需要将单个函数拆分为 4 个进程的简单进程很有用,但我的问题是需要一个进程池在后台不断运行,而另一个 2 个进程池等待预处理数据。

标签: python multithreading python-2.7 multiprocessing


【解决方案1】:

这是实现您想要的尝试的尝试:

...

# Mapping functions can only take one arg, we provide tuple
def img_resize_splat(a):
    img_resize(*a)

if __name__=="__main__":
    # Make a CPU pool and a GPU pool
    cpu = Pool(4)
    gpu = Pool(2)

    # Hopefully this returns an iterable, and not a list with all images read into memory
    img_list = read_images("path/to/images/")

    # I'm assuming you want images to be processed as soon as ready, order doesn't matter
    resized = cpu.imap_unordered(img_resize_splat, ((img, 100, 100) for img in img_list))
    converted = gpu.imap_unordered(convert_bw, resized)

    # This is an iterable with your results, slurp them up one at a time
    for bw_img in converted:
        # do something

【讨论】:

  • 我喜欢你的例子,但我有一些问题。图像列表可以小到 1000,但可以大到 100,000,所以我想限制队列的大小。我希望运行 4 个并发进程来填充最大大小为 10 的队列,并在 GPU 2 一次从队列中删除图像时继续填充它。顺序无关紧要,但似乎队列并没有在 cpu..imap_unordered() 中被控制?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多