Python并行处理大文件时不释放RAM

时间:2016-07-19 23:29:17

标签: python python-3.x memory-management parallel-processing

我有一个25Gb的纯文本文件,大约有1000万行,每行有几百个字。每条线都需要单独处理,我试图将块拆分为十几个并行处理的工人。目前一次加载一百万行(由于某种原因,它在RAM中占用~10Gb,即使它只在磁盘上解压缩为3Gb),将它分成12个方向,然后使用多处理将其映射到12个工作者.Pool。

问题是,当我的12名工作人员完成处理他们分配的数据时,他们的RAM没有被释放,并且在下一次百万行迭代中只增加了~10Gb。

我已经尝试了以前的数据,将以前的数据重置为空分配,然后使用eval(),gc.collect()创建可迭代的变量名称删除,并完全将IO分离到自己的功能,所有这些都没有运气和完全相同的问题。运行调试表明python解释器只识别预期的数据,并且无法访问上一次迭代的数据,为什么RAM实际上没有被释放?

下面的代码是我尝试分离所有环境的最新版本,而不是最有效但是" BigFileOnDisk"在SSD上,因此每次重复读取文件与实际处理数据相比可忽略不计。以前有过"阅读"分配功能中的功能,在工人完成后删除所有数据,结果相同。

def allocation():
    fileCompleted = False
    currentLine = 0
    while not fileCompleted:
        lineData, currentLine, fileCompleted = read(numLines=1000000, startLine=currentLine)
        list_of_values(function_object=worker, inputs=lineData, workers=12)


def read(numLines, startLine=0):
    currentLine = 0
    lines = []
    with open(BigFileOnDisk, 'r') as fid:
        for line in fid:
            if currentLine >= startLine:
                lines.append(line)
            if currentLine - startLine >= numLines:
                return lines, counter, False
            currentLine += 1
        # or if we've hit the end of the file
        return lines, counter, True


def worker(lines):
    outputPath = *root* + str(datetime.datetime.now().time())
    processedData = {}

    for line in lines:
        # process data

    del lines
    with open(outputPath, 'a') as fid:
        for item in processedData:
            fid.write(str(item) + ', ' + str(processedData[item]) + '\n')


def list_of_values(function_object, inputs, workers = 10):
    inputs_split = []
    subsection_start = 0
    for n in range(workers):
        start = int(subsection_start)
        end = int(subsection_start + len(inputs) / workers)
        subsection_start = end

        inputs_split.append( inputs[start:end] )

    p = Pool(workers)
    p.map(function_object, inputs_split)

1 个答案:

答案 0 :(得分:4)

您没有加入子流程。 list_of_values创建的Pool个完成的进程仍然活着之后(有点像僵尸,但有活着的父进程)。他们仍然拥有所有的价值观。您无法在main中看到他们的数据,因为它在另一个进程中(出于同样的原因gc.collect无效)。

要释放工作人员分配的内存,您需要手动加入Pool或使用with

def list_of_values(function_object, inputs, workers = 10):
    inputs_split = []
    subsection_start = 0
    for n in range(workers):
        start = int(subsection_start)
        end = int(subsection_start + len(inputs) / workers)
        subsection_start = end

        inputs_split.append( inputs[start:end] )

    with Pool(workers) as p:
        p.map(function_object, inputs_split)