我尝试使用类似MapReduce的方式使用多个线程来计算大型文档池中大量单词的出现。每个线程都以一个字典开始,该字典将语料库中的每个单词映射为零,并在计数越过文档时递增计数。一旦完成所有线程,我想累积计数。我将第一个json文件加载到内存中并循环遍历其余部分,总结计数:
setUp()
此处collectstatic
是包含所有最终计数的最终字典。 def merge_counts(self):
path = os.path.join(self.get_current_job_directory(), 'batch_0.json')
with open (path, 'r') as json_file:
kmers = json.load(json_file)
batch = None
for i in range(1, self.num_threads):
path = os.path.join(self.get_current_job_directory(), 'batch_' + str(i) + '.json')
with open (path, 'r') as json_file:
batch = json.load(json_file)
for kmer in batch:
kmers[kmer] += batch[kmer]
batch = None
return kmers
内的密钥数量无论加载多少个批次都保持不变,因为它们只有不同的计数才具有相同的密钥。每个json文件大约3 gig,所以最终结果也大致相同。我希望这段代码能够使用尽可能多的内存,就像在内存中保存两个这样的json文件(迄今为止的共识和当前批处理)作为字典,但内存使用量随每个批量线性增长,直到我最终耗尽内存。为什么会这样?当我将它设置为kmers
时,变量kmers
引用的先前的东西是不是被垃圾收集了?
更新:所以我在每次循环迭代结束时添加了batch
,内存在每次迭代时仍然呈线性增长。有什么想法吗?
答案 0 :(得分:0)
我确定您现在已经解决了这个问题,但是最近我遇到了类似的问题,而且很难找到答案。因此,在此处发布我的解决方案以作记录。
大型文件上的json.load()
(或loads()
)似乎可以防止batch
由于某些引用而被垃圾回收,从而导致大量内存泄漏。
不过,使batch
成为json.load()的深层副本似乎允许python正确运行垃圾回收。所以:
import copy
...
batch = copy.deepcopy(json.load(json_file))
...
gc.collect()
还没来得及研究为什么会发生这种情况,但是对于我来说似乎是可行的。