并行文件解析,多个CPU核心

时间:2010-10-28 22:57:01

标签: python python-3.x parallel-processing

我之前问了一个相关但非常普遍的问题(特别参见this response)。

这个问题非常具体。这是我关心的所有代码:

result = {}
for line in open('input.txt'):
  key, value = parse(line)
  result[key] = value

函数parse完全是自包含的(即不使用任何共享资源)。

我有Intel i7-920 CPU(4核,8个线程;我认为线程更相关,但我不确定)。

如何让我的程序使用该CPU的所有并行功能?

我假设我可以打开此文件以便在8个不同的线程中读取,而不会造成太多性能损失,因为磁盘访问时间相对于总时间而言很小。

6 个答案:

答案 0 :(得分:18)

cPython不提供您正在寻找的线程模型。您可以使用multiprocessing模块和process pool

获得类似的内容

这样的解决方案看起来像这样:

def worker(lines):
    """Make a dict out of the parsed, supplied lines"""
    result = {}
    for line in lines.split('\n'):
        k, v = parse(line)
        result[k] = v
    return result

if __name__ == '__main__':
    # configurable options.  different values may work better.
    numthreads = 8
    numlines = 100

    lines = open('input.txt').readlines()

    # create the process pool
    pool = multiprocessing.Pool(processes=numthreads)

    # map the list of lines into a list of result dicts
    result_list = pool.map(worker, 
        (lines[line:line+numlines] for line in xrange(0,len(lines),numlines) ) )

    # reduce the result dicts into a single dict
    result = {}
    map(result.update, result_list)

答案 1 :(得分:8)

  1. 将文件拆分为8个较小的文件
  2. 启动单独的脚本来处理每个文件
  3. 加入结果
  4. 为什么这是最好的方式...

    • 这很简单 - 你不必以任何方式编程,不同于线性处理。
    • 通过启动少量长时间运行的流程,您可以获得最佳性能。
    • 操作系统将处理上下文切换和IO多路复用,因此您不必担心这些问题(操作系统做得很好)。
    • 您可以扩展到多台计算机,而无需更改代码
    • ...

答案 2 :(得分:3)

这可以使用Ray完成,Ray documentation是一个用于编写并行和分布式Python的库。

要运行下面的代码,请首先如下创建input.txt

printf "1\n2\n3\n4\n5\n6\n" > input.txt

然后,您可以通过向@ray.remote函数添加parse装饰器并按如下所示并行执行许多副本来并行处理文件

import ray
import time

ray.init()

@ray.remote
def parse(line):
    time.sleep(1)
    return 'key' + str(line), 'value'

# Submit all of the "parse" tasks in parallel and wait for the results.
keys_and_values = ray.get([parse.remote(line) for line in open('input.txt')])
# Create a dictionary out of the results.
result = dict(keys_and_values)

请注意,执行此操作的最佳方法取决于运行parse函数所花费的时间。如果需要一秒钟(如上所述),则每个Ray任务解析一行是有意义的。如果需要1毫秒,则可能有必要解析每个Ray任务的一行代码(例如100条)。

您的脚本很简单,因此也可以使用多处理模块,但是,一旦您想做更复杂的事情或想利用多台计算机而不是一台计算机,那么使用Ray就会容易得多。 / p>

请参见sample data

答案 3 :(得分:0)

您可以使用multiprocessing模块,但如果parse()很快,那么这样做不会带来太多的性能提升。

答案 4 :(得分:0)

正如TokenMacGuy所说,您可以使用multiprocessing模块。如果您确实需要解析大量数据,请查看 disco project

  

Disco 是一种分布式计算   基于MapReduce的框架   范例。迪斯科是开源的;   由诺基亚研究中心开发   解决处理中的实际问题   大量数据。

它真正适用于你的parse()作业是“纯粹”(即不使用任何共享资源)并且是CPU密集型的作业。我在一个核心上测试了一个作业,然后比较了在3个主机上运行它,每个主机有8个核心。在Disco群集上运行时,它实际上运行快了24倍(注意:测试了一个不合理的CPU密集型作业)。

答案 5 :(得分:0)

  • 使用rabbitMQ制作分布式架构,一个任务生成器逐行读取文件并通过rabbitMQ向工作人员发送行
  • 使用控制台实用程序,如unix / parallel,xargs
    $ python makelist.py | parallel -j+2 'wget "{}" -O - | python parse.py'
    
    或者这种风格
$ ls *.wav | xargs -n1 --max-procs=4 -I {} lame {} -o {}.mp3

无论如何,你需要实现map / reduce范例