python在处理数据的时候,memory-heavy 的数据往往会导致程序没办反运行或者运行期间服务器其他程序效率受到影响。这种情况往往会把数据集合变为通过genertor来遍历。

但同时如我们所知,generoter看似只能被单进程消费,这样效率很低。

generator 可以被pool.map消费。

看一下pool.py的源码。

for i, task in enumerate(taskseq):
     ...
     try:
         put(task)
     except IOError:
         debug(\'could not put task on queue\')
         break

实际是先将generator全部消费掉放到queue中。然后通过map来并行。这样是解决了使用map来并行。

但是依然没有解决占用内存的问题。这里有两步占用内存。

  • 第一步是全部消费掉的generator。
  • 第二步并行运算全部data。

解决第一个问题,通过部分消费generator来达到。
解决第二个问题,可以通过imap来达到.

示例代码如下:

import multiprocessing as mp
import itertools
import time


def g():
    for el in xrange(50):
        print el
        yield el

import os

def f(x):
    time.sleep(1)
    print str(os.getpid()) +\" \"+  str(x)
    return x * x

if __name__ == \'__main__\':
    pool = mp.Pool(processes=4)              # start 4 worker processes
    go = g()
    result = []
    N = 11
    while True:
        g2 = pool.imap(f, itertools.islice(go, N))
        if g2:
            for i in g2:
                result.append(i)
                time.sleep(1)
        else:
            break
    print(result)

ps: 使用注意事项。在produce数据的时候,尽量少做操作,应为即使是map也是单线程的来消费数据。所以尽量把操作放到map中作。这样才能更好的利用多进程提高效率。