11

我们需要处理的各个目录中有大约 500GB 的图像。每个图像大小约为 4MB,我们有一个 python 脚本来一次处理每个图像(它读取元数据并将其存储在数据库中)。每个目录可能需要 1-4 小时来处理,具体取决于大小。

我们可以在 GNU/Linux 操作系统上使用 2.2Ghz 四核处理器和 16GB RAM。当前脚本仅使用一个处理器。利用其他内核和 RAM 更快地处理图像的最佳方法是什么?启动多个 Python 进程来运行脚本会利用其他内核吗?

另一种选择是使用 Gearman 或 Beanstalk 之类的工具将工作外包给其他机器。我查看了多处理库,但不确定如何使用它。

4

6 回答 6

6

启动多个 Python 进程来运行脚本会利用其他内核吗?

是的,如果任务是 CPU 密集型的,它会的。这可能是最简单的选择。但是,不要为每个文件或每个目录生成一个进程;考虑使用一个工具,比如parallel(1)让它在每个核心产生两个进程。

另一种选择是使用 Gearman 或 Beanstalk 之类的工具将工作外包给其他机器。

那可能行得通。另外,看看ZeroMQ 的 Python 绑定,它使分布式处理变得非常容易。

我查看了多处理库,但不确定如何使用它。

定义一个函数,例如process,读取单个目录中的图像,连接到数据库并存储元数据。让它返回一个指示成功或失败的布尔值。让directories成为要处理的目录列表。然后

import multiprocessing
pool = multiprocessing.Pool(multiprocessing.cpu_count())
success = all(pool.imap_unordered(process, directories))

将并行处理所有目录。如果需要,您还可以在文件级别进行并行处理;这需要更多的修补。

请注意,这将在第一次失败时停止;使其容错需要更多的工作。

于 2012-04-04T14:17:30.107 回答
4

启动独立的 Python 进程是理想的。进程之间不会有锁争用,操作系统会安排它们同时运行。

您可能想尝试看看理想的实例数是多少 - 它可能多于或少于核心数。磁盘和缓存内存会发生争用,但另一方面,您可能会在另一个进程等待 I/O 时运行一个进程。

于 2012-04-04T14:18:53.160 回答
4

您可以使用多处理池来创建进程以提高性能。假设您有一个用于处理图像的函数 handle_file。如果您使用迭代,它最多只能使用一个核心的 100%。为了利用多核,池多处理为您创建子进程,并将您的任务分配给它们。这是一个例子:

import os
import multiprocessing

def handle_file(path):
    print 'Do something to handle file ...', path

def run_multiprocess():
    tasks = []

    for filename in os.listdir('.'):
        tasks.append(filename)
        print 'Create task', filename

    pool = multiprocessing.Pool(8)
    result = all(list(pool.imap_unordered(handle_file, tasks)))
    print 'Finished, result=', result

def run_one_process():
    for filename in os.listdir('.'):
        handle_file(filename)

if __name__ == '__main__':
    run_one_process
    run_multiprocess()

run_one_process 是处理数据的单核方式,简单但速度慢。另一方面,run_multiprocess 创建 8 个工作进程,并将任务分配给它们。如果你有 8 个核心,它会快 8 倍。我建议您将工作人员数量设置为核心数量的两倍或恰好是核心数量。您可以尝试一下,看看哪种配置更快。

对于高级分布式计算,您可以使用ZeroMQ作为 larsmans 提到的。一开始很难理解。但是一旦你理解了它,你就可以设计一个非常高效的分布式系统来处理你的数据。在您的情况下,我认为一个具有多个 REP 的 REQ 就足够了。

在此处输入图像描述

希望这会有所帮助。

于 2012-04-04T14:51:00.917 回答
2

请参阅此问题的答案

如果应用程序可以处理输入数据范围,那么您可以启动 4 个具有不同输入数据范围的应用程序实例进行处理,并在它们全部完成后合并结果。

尽管这个问题看起来是特定于 Windows 的,但它适用于所有操作系统上的单线程程序。

警告:请注意,此进程将受 I/O 限制,并且对硬盘驱动器的过多并发访问实际上会导致进程作为一个组执行比顺序处理,因为争用 I/O 资源。

于 2012-04-04T14:21:58.590 回答
0

如果您正在读取大量文件并将元数据保存到数据库中,则您的程序不需要更多内核。

您的进程可能是 IO 限制而不是 CPU 限制。使用带有适当延迟和回调的扭曲可能会胜过任何试图争取 4 个核心的解决方案。

于 2012-04-04T15:13:45.897 回答
0

我认为在这种情况下使用Celery非常有意义。

于 2015-01-22T12:24:31.097 回答