在构建大型列表dict的同时,内存使用量急剧增加

2024-05-16 04:01:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在从文本标记化过程中生成大量嵌套列表,并希望将它们存储在dict中,其中的键与源dict中字符串的键相关

源dict示例:

{
    '1' : 'the horse',
    '2' : 'grass is green',
    ...
}

期望输出的示例,其中整数是标记化和哈希过程的输出:

^{pr2}$

当我迭代我的源dict,向我的标记化函数输入值,并将键、标记化的值对分配给一个新dict时,我的新dict使用的内存量远远大于它应该占用的实际空间。在

下面是一些模拟代码来说明我的问题:

import gc
import numpy as np
import matplotlib.pyplot as plt
import sys
import json

import os
import psutil

pid = os.getpid()
py = psutil.Process(pid)

def memory_use():
    memoryUse = py.memory_info()[0]/2.**30  # memory use in GB
    return memoryUse

def tokenize_sim():
    # returns a list of 30 lists of 4 random ints
    # (simulates 30 tokenized words)
    return [[int(n) for n in np.random.randint(low=0, high=1e6, size=4)] for i in range(31)]

memory = []
tokens = dict()
for i in range(800001):
    tokens[i] = tokenize_sim()
    if i % 50000 == 0:
        memoryUse = memory_use()
        print(i, '- memory use:', memoryUse)
        memory.append(memoryUse)

plt.figure()
plt.plot(np.arange(17)*50, memory)
plt.grid()
plt.xlabel('Thousands of iterations')
plt.ylabel('Memory used in GB')
plt.show()

print('System size in bytes:', sys.getsizeof(tokens))

以下是内存使用情况图:

Linear growth of memory usage

sys.getsizeof(tokens)返回41943144字节。我试着把这个dict写到一个json文件中,这个文件使用了821MB。所有这些都没有接近6GB的内存。在

我错过了什么?我猜这是内存分配问题,但我还没有找到任何解决方案。我需要处理大约1200万个词条的源字典,而我的64GB内存似乎不足以构建一个列表dict。任何帮助都将不胜感激。在


Tags: of内存in标记importforuse过程
1条回答
网友
1楼 · 发布于 2024-05-16 04:01:31

除了绘制内存使用情况之外,我真的无法理解您在做什么(可能想删除与问题无关的代码),但我可以给您一些一般性的建议,如何处理大量数据,以及为什么它会占用您的所有内存。在

原因。就效率和速度而言,Python并不是一种真正的高性能语言。在Python中,一切都是一个对象,每个对象都有自己的属性。当您创建一个嵌套的属性列表时,父列表、所有嵌套列表和每个小整数都会附加它们自己的内容—它们自己的元数据和描述。当您在不同的对象上调用dir()时,您可以看到这一点——例如,Python中的一个整数有69个不同的方法和属性。所有这些都必须放在内存中,这就是为什么你的内存被占用的速度比JSON格式的实际大小要快得多,JSON格式不包含任何关于数据的元数据。在

如何与之抗衡?有些语言在处理大量数据方面比其他语言好得多,仅仅是因为它们对开发人员不太友好,而且每一步都在为您着想。您可以切换到C并使用8GB的RAM完成任务。
但我不建议转换语言,只是使用一些更好的实践。你的数据现在都在你的字典里了吗这真的没有效率。看看numpy熊猫能为您做些什么-它们正是针对这样的用例而设计的。它们是用C语言实现的,它提供了更好的性能,同时有一个pythonapi,使用起来非常方便。在

如果这还不够,那就分批做你正在做的事情。如果你想要的是一个包含一些整数的大列表,你可以在迭代中完成,同时每隔一段时间保存所有的列表,你不需要同时把它们都放在内存中。如果Python本机垃圾回收还不够,可以尝试通过del调用垃圾回收来强制Python释放内存。在

import gc
del big_bad_variable
gc.collect()

相关问题 更多 >