可以使用joblib并行化分析。如果有函数process_line:from joblib import Parallel, delayed
data = Parallel(n_jobs=-1)(delayed(process_line)(line)
for line in open('bigfile'))
您要连续保存信息。根据要保存的计算时间/数据大小的比率,可以使用不同的方法:
需要大量计算时间才能得到一些数字
线程之间的通信开销非常小。最简单的方法是让每个进程写在一个独立的文件上,并在最后将结果汇总在一起。通过传递索引并使用它创建文件,可以确保不会被覆盖。
更高级的解决方案是将文件处理程序作为参数传递,并仅在获取multiprocessing.Lock之后才写入文件。唯一的问题是,如果许多进程试图同时获取锁,它们将占用CPU资源,而不是计算。def process_line(line, outfile, lock)
data = line[0]
lock.aquire()
print >> outfile, data
lock.release()
缩短计算时间
如果你有更多的数据,写入一个文件可能会导致一些开销,特别是如果你打算在以后重新加载到内存中。你有两个选择:所有的数据都在记忆中:你很幸运。使用joblib,只需使其成为函数的返回。在最后你有一个你的所有结果的顺序列表。
数据不适合内存,您必须动态使用它。你需要一个消费生产者模式。类似于:from multiprocessing import Process, JoinableQueue
from joblib import Parallel, delayed
def saver(q):
with open('out.txt', 'w') as out:
while True:
val = q.get()
if val is None: break
print >> out, val
q.task_done()
# Finish up
q.task_done()
def foo(x):
q.put(x**3+2)
q = JoinableQueue()
p = Process(target=saver, args=(q,))
p.start()
Parallel(n_jobs=2, verbose=0)(delayed(foo)(i) for i in xrange(1000))
q.put(None) # Poison pill
q.join()
p.join()
如果与计算时间相比,数据量非常大,那么只需将数据从一个进程传输到另一个进程,就会发现大量开销。如果这是你的极限,那么你应该使用更先进的技术,比如OpenMP,或者Cython来摆脱GIL,使用线程而不是进程。
请注意,我没有指定“小”有多小;因为这在很大程度上取决于集群的配置。通信、底层文件系统等的速度有多快;但没有什么是您不容易尝试的,例如,计时虚拟程序向另一个进程发送一行代码所需的时间。