用Python处理大型文件的最快方法

用Python处理大型文件的最快方法,python,optimization,parallel-processing,Python,Optimization,Parallel Processing,我们需要处理的不同目录中有大约500GB的图像。每个图像的大小约为4MB,我们有一个python脚本一次处理一个图像(它读取元数据并将其存储在数据库中)。根据大小,每个目录可能需要1-4小时才能处理 在GNU/Linux操作系统上,我们拥有一个2.2Ghz的四核处理器和16GB的RAM。当前脚本仅使用一个处理器。利用其他内核和RAM更快地处理图像的最佳方法是什么?启动多个Python进程来运行脚本会利用其他内核吗 另一种选择是使用Gearman或Beanstalk之类的工具将工作外包给其他机器。

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

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

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

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

是的,如果任务是CPU受限的,它会。这可能是最简单的选择。但是,不要为每个文件或目录生成单个进程;考虑使用一个工具,例如,让它产生一个类似于每个核的两个进程。 另一种选择是使用Gearman或Beanstalk之类的工具将工作外包给其他机器

那可能行得通。另外,看一下,它使分布式处理变得非常简单

我看过多处理库,但不确定如何利用它

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

import multiprocessing
pool = multiprocessing.Pool(multiprocessing.cpu_count())
success = all(pool.imap_unordered(process, directories))
将并行处理所有目录。如果需要,还可以在文件级执行并行处理;这需要更多的修补


注意,这将在第一次故障时停止;使其具有容错性需要更多的工作。

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

您可能需要进行实验,以了解理想的实例数是多少——它可能多于或少于内核数。磁盘和缓存内存将存在争用,但另一方面,您可能会让一个进程运行,而另一个进程正在等待I/O。

请参阅相关说明

如果应用程序可以处理输入数据的范围,那么您可以启动4 要处理的输入数据范围不同的应用程序实例 并在所有操作完成后将结果合并

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


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

您可以使用多处理池来创建进程以提高效率演出比方说,您有一个函数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_进程是处理数据的单核心方式,简单但缓慢。另一方面,run_multiprocess创建8个辅助进程,并将任务分发给它们。如果你有8个内核,速度会快8倍。我建议您将工人数量设置为核心数量的两倍,或者正好是核心数量。您可以试试看哪种配置更快

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


希望这会有所帮助。

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


您的进程可能是IO绑定的,而不是CPU绑定的。使用twisted和适当的延迟和回调可能会比任何寻求使用4核的解决方案表现更好

> P>我认为在这种情况下使用它是完全有意义的。

可能的副本,如果你已经有一个工作脚本,你可以指向任何你想要的文件/目录,考虑写一个shell脚本来旋转你需要的许多实例。如果你把大部分时间都花在执行IO上,那么你的速度就快不了多少。例如,如果一个进程以一定的速度从磁盘加载数据,那么当多个进程在咀嚼磁盘时,很可能无法保持该速度。我非常同意Jeff Forster的观点,首先要查找瓶颈。如果您对文件所做的唯一处理就是读取元数据并存储它们,那么很有可能您的瓶颈是磁盘访问。因此,尝试添加更多访问同一磁盘的进程只会降低性能。