Python 大数据多处理

Python 大数据多处理,python,multiprocessing,generator,Python,Multiprocessing,Generator,我正在使用multiprocessing.Pool()来并行化一些繁重的计算 目标函数返回大量数据(一个巨大的列表)。我的内存快用完了 如果没有多处理,我只需将目标函数更改为生成器,方法是在计算结果元素时,一个接一个地生成结果元素 我知道多处理不支持生成器——它等待整个输出并立即返回,对吗?不屈服。有没有一种方法可以使池工作者在数据可用时立即生成数据,而不必在RAM中构建整个结果数组 简单的例子: def target_fnc(arg): result = [] for i in x

我正在使用
multiprocessing.Pool()
来并行化一些繁重的计算

目标函数返回大量数据(一个巨大的列表)。我的内存快用完了

如果没有
多处理
,我只需将目标函数更改为生成器,方法是
在计算结果元素时,一个接一个地生成结果元素

我知道多处理不支持生成器——它等待整个输出并立即返回,对吗?不屈服。有没有一种方法可以使
工作者在数据可用时立即生成数据,而不必在RAM中构建整个结果数组

简单的例子:

def target_fnc(arg):
   result = []
   for i in xrange(1000000):
       result.append('dvsdbdfbngd') # <== would like to just use yield!
   return result

def process_args(some_args):
    pool = Pool(16)
    for result in pool.imap_unordered(target_fnc, some_args):
        for element in result:
            yield element
def target_fnc(arg):
结果=[]
对于X范围内的i(1000000):

result.append('dvsdbdfbngd')#这听起来像是队列的理想用例:

只需将您的结果从汇集的工作人员输入队列,并在主服务器中接收它们


请注意,您仍然可能会遇到内存压力问题,除非您以与工作人员填充队列一样快的速度排空队列。您可以限制队列大小(适合队列的对象的最大数量),在这种情况下,池中的工作人员将阻塞
队列。放置
语句,直到队列中有可用空间。这将限制内存使用。但是,如果您正在这样做,可能是时候重新考虑是否需要池和/或使用更少的工作人员是否有意义了。

如果您的任务可以分块返回数据……它们是否可以分为更小的任务,每个任务返回单个块?显然,这并不总是可能的。如果不是这样,则必须使用其他机制(如Loren Abrams建议的
队列
)。但如果是这样,出于其他原因,这可能是一个更好的解决方案,同时也解决了这个问题

以你的例子来说,这当然是可行的。例如:

def target_fnc(arg, low, high):
   result = []
   for i in xrange(low, high):
       result.append('dvsdbdfbngd') # <== would like to just use yield!
   return result

def process_args(some_args):
    pool = Pool(16)
    pool_args = []
    for low in in range(0, 1000000, 10000):
        pool_args.extend(args + [low, low+10000] for args in some_args)
    for result in pool.imap_unordered(target_fnc, pool_args):
        for element in result:
            yield element
def target_fnc(arg):
    fd, path = tempfile.mkstemp(text=True)
    with os.fdopen(fd) as f:
        for i in xrange(1000000):
            f.write('dvsdbdfbngd\n')
    return path

def process_args(some_args):
    pool = Pool(16)
    for result in pool.imap_unordered(target_fnc, some_args):
        with open(result) as f:
            for element in f:
                yield element
def target_fnc(arg、低、高):
结果=[]
对于X范围内的i(低、高):

result.append('dvsdbdfbngd')#根据您的描述,听起来您对处理传入的数据不太感兴趣,而是对避免将一百万元素
列表
传回感兴趣

有一种更简单的方法:将数据放入一个文件中。例如:

def target_fnc(arg, low, high):
   result = []
   for i in xrange(low, high):
       result.append('dvsdbdfbngd') # <== would like to just use yield!
   return result

def process_args(some_args):
    pool = Pool(16)
    pool_args = []
    for low in in range(0, 1000000, 10000):
        pool_args.extend(args + [low, low+10000] for args in some_args)
    for result in pool.imap_unordered(target_fnc, pool_args):
        for element in result:
            yield element
def target_fnc(arg):
    fd, path = tempfile.mkstemp(text=True)
    with os.fdopen(fd) as f:
        for i in xrange(1000000):
            f.write('dvsdbdfbngd\n')
    return path

def process_args(some_args):
    pool = Pool(16)
    for result in pool.imap_unordered(target_fnc, some_args):
        with open(result) as f:
            for element in f:
                yield element
显然,如果您的结果可以包含换行符,或者不是字符串等,那么您将希望使用
csv
文件、
numpy
等,而不是简单的文本文件,但想法是一样的


这就是说,即使这更简单,一次一块地处理数据通常也有好处,因此,如果有缺点的话,分解任务或使用
队列
(如其他两个答案所示)可能会更好(分别是,需要一种分解任务的方法,或者必须能够以生成数据的速度使用数据)排队不是通过数据处理的。

队列将通过酸洗数据。所以数据->泡菜> uncle ->数据的新副本。这将减慢程序并使用更多的额外RAM。应该考虑使用共享内存代替。有趣的解决方案。但是<代码> TimeFrase/COD>(TMP文件系统)需要在RAM中。但是我们今天可以在每个操作系统配置中假设它吗?