将数据作为后台进程在Python中写入磁盘

时间:2013-04-25 12:25:34

标签: python file multiprocessing

我有一个Python程序基本上可以执行以下操作:

for j in xrange(200):
    # 1) Compute a bunch of data
    # 2) Write data to disk

1)大约需要2-5分钟 2)大约需要1分钟

请注意,内存中存储的数据太多。

理想情况下,我想要做的是以避免空闲CPU的方式将数据写入磁盘。这在Python中可行吗?谢谢!

3 个答案:

答案 0 :(得分:9)

您可以尝试这样using multiple processes

import multiprocessing as mp

def compute(j):
    # compute a bunch of data
    return data

def write(data):
    # write data to disk

if __name__ == '__main__':
    pool = mp.Pool()
    for j in xrange(200):
        pool.apply_async(compute, args=(j, ), callback=write)
    pool.close()
    pool.join()

pool = mp.Pool()将创建一个工作进程池。默认情况下,worker的数量等于您的计算机具有的CPU核心数。

每个pool.apply_async调用将由工作进程池中的工作者运行的任务排队。当工作人员可用时,它将运行compute(j)。当worker返回一个值data时,主进程中的一个线程运行回调函数write(data),其中data是工作者返回的数据。

一些警告:

  • 数据必须是可选择的,因为它是从数据传输的 工作人员通过Queue回复主要流程。
  • 无法保证工人完成的顺序 任务与任务发送到的任务顺序相同 池。因此,数据写入磁盘的顺序可能不会 对应于j,范围从0到199.解决此问题的一种方法 将数据写入sqlite(或其他类型)数据库 将j作为数据字段之一。然后,当你想阅读 按顺序排列的数据,您可以SELECT * FROM table ORDER BY j
  • 使用多个进程会增加所需的内存量 因为数据是由工作进程生成的,等待写入磁盘的数据会累积在队列中。您 可能能够减少使用NumPy所需的内存量 阵列。如果那是不可能的,那么你可能不得不减少 进程数:

    pool = mp.Pool(processes=1) 
    

    这将创建一个工作进程(运行compute),离开 运行write的主要流程。由于compute需要更长时间 write,队列不会备份超过一个块 要写入磁盘的数据。但是,您仍然需要足够的内存 在写一个不同的块时计算一个数据块 数据到磁盘。

    如果您没有足够的内存同时执行这两项操作,那么您别无选择 - 您的原始代码是顺序运行computewrite的唯一方法。

答案 1 :(得分:3)

您可以使用Queue.Queue(模块位于此处:Queue)和threading.Thread(或threading.start_new_thread,如果您只需要一个功能),模块是这里:threading - 由于文件写入不是CPU密集型并且使用更多IO。 (并且GIL不会影响它)。

答案 2 :(得分:2)

简单的方法是只使用线程和队列。另一方面,如果计算部分不依赖于全局状态,并且您的计算机具有多个CPU核心,则使用process pool

的效率更高。
from multiprocessing import Pool

def compute_data(x):
    return some_calculation_with(x)

if __name__ == '__main__':
    pool = Pool(processes=4) # let's say you have quad-core, so start 4 workers

    with open("output_file","w") as outfile:
        for calculation_result in pool.imap(compute_data, range(200)):
        # pool.imap returns results as they come from process pool    
            outfile.write(calculation_result)