7

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

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

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

请注意,要保存在内存中的数据太多。

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

4

3 回答 3

11

您可以尝试使用这样的多个进程

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作为worker返回的数据。

一些警告:

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

    pool = mp.Pool(processes=1) 
    

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

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

于 2013-04-25T12:33:06.380 回答
3

您可以使用诸如Queue.Queue(模块在这里:队列)和threading.Thread(或者threading.start_new_thread如果您只想要一个函数),模块在这里:线程- 因为文件写入不是 CPU 密集型并使用更多 IO。(并且 GIL 不会影响它)。

于 2013-04-25T12:29:15.440 回答
2

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

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)  
于 2013-04-25T12:40:28.207 回答