首页 文章

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

提问于
浏览
11

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

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

另一个选择是使用Gearman或Beanstalk之类的东西将工作分配给其他机器 . 我已经看了多处理库但不知道如何利用它 .

6 回答

  • 2

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

    是的,如果任务受CPU约束,它将会 . 这可能是最简单的选择 . 但是,不要为每个文件或每个目录生成单个进程;考虑使用诸如parallel(1)之类的工具,让它产生类似于每个核心两个进程的东西 .

    另一个选择是使用Gearman或Beanstalk之类的东西将工作分配给其他机器 .

    那可能有用 . 另外,看看Python binding for ZeroMQ,它使分布式处理变得非常简单 .

    我看了一下多处理库,但不知道如何利用它 .

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

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

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

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

  • 6

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

    您可能希望尝试查看理想的实例数 - 它可能多于或少于核心数 . 将存在争用磁盘和高速缓存的问题,但另一方面,您可能会运行一个进程而另一个进程正在等待I / O.

  • 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就足够了 .

    enter image description here

    希望这会有所帮助 .

  • 0

    请参阅answerquestion .

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

    即使该问题看起来是特定于Windows的,它也适用于所有操作系统上的单线程程序 .

    WARNING: 请注意,此进程将受I / O限制,并且由于争用I / O资源,对硬盘驱动器的并发访问过多实际上会导致进程作为一个组执行 slower 而不是顺序处理 .

  • 0

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

    您的进程可能是IO绑定而不是CPU绑定 . 使用扭曲的适当的延迟和回调可能会胜过任何寻求争取4核的解决方案 .

  • 4

    我认为在这种情况下使用Celery是完全合理的 .

相关问题