【问题标题】:Memory error when working with large text corpus处理大型文本语料库时出现内存错误
【发布时间】:2016-12-21 10:32:46
【问题描述】:

我有一个大文本文件(~450MB -> 129,000 行和 457,000,000 个字符),一段时间后我尝试使用此文件时,Memory Error 上升,这是我的代码:

docDict = {}
ind = 1

with open('somefile.txt',encoding='utf-8') as f:
    for line in f:
        data = line.split(' ')
        docDict[ind] = data
        ind+=1

我看到了 this ,但我逐行读取文件。

【问题讨论】:

    标签: python memory corpus


    【解决方案1】:

    为了测试代码中数据结构的开销,我编写了以下测试程序。它假定您的文本文件是 ASCII 编码的N 兆字节,行数相对较短。 (我的物理内存耗尽后,我不得不将N 从 450 更改为 150。)

    import sys
    
    MB = 1024 * 1024
    
    line = "the quick brown fox jumps over the lazy dog"
    megs = 150
    nlines = (megs * MB) / len(line)
    
    d = {}
    for i in xrange(nlines):
        d[i] = line.split(' ')
    
    dict_size = sys.getsizeof(d)
    list_size = sum(sys.getsizeof(a) for a in d.items())
    item_size = sum(sum(sys.getsizeof(s) for s in a) for a in d.items())
    
    print " dict:", dict_size / float(MB), "MB"
    print "lists:", list_size / float(MB), "MB"
    print "items:", item_size / float(MB), "MB"
    print "total:", (dict_size + list_size + item_size) / float(MB), "MB"
    

    结果:

     dict: 192.00 MB
    lists: 251.16 MB
    items: 669.77 MB
    total: 1112.9 MB
    

    查看Activity Monitor,Python进程的内存使用量超过了2GB,所以也有一些内存没有计入。 malloc 实现的工件可能是一种可能性。

    我用 C++ 实现了相同的程序:

    #include <string>
    #include <vector>
    #include <unordered_map>
    
    int main()
    {
        int const MB = 1024 * 1024;
    
        std::string const line = "the quick brown fox jumps over the lazy dog";
        std::vector<std::string> const split = {
            "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"
        };
    
        int const megs = 150;
        int const nlines = (megs * MB) / line.size();
    
        std::unordered_map<int, std::vector<std::string>> d;
        for (int i = 0; i < nlines; ++i) {
            d[i] = split;
        }
    }
    

    使用clang++ -O3 编译,使用了大约 1GB 的内存。 C++ 没有sys.getsizeof(),所以它需要更多的工作来分解内存使用,我没有做那个工作。

    两倍于等效 C++ 的内存实际上对于 Python 来说是一个相当不错的结果,因此我将删除关于 cPython 实现的预编辑 cmets。

    我认为您的主要问题是将行存储为短字符串数组。您是否可以将这些行存储为整个字符串并根据需要将它们拆分,但不能一次全部拆分?

    你的计划的最终目标是什么?

    【讨论】:

    • 不幸的是,每行至少有 100 到 1000 字!!如何使我的代码复杂化?
    • 实际上,如果我将程序更改为line = 10 * "the quick brown fox jumps over the lazy dog",内存使用量会下降很多,即使是items。这令人惊讶 - 我只希望 dictlist 开销下降。
    • 添加了 C++ 比较和新结论,请参阅编辑。
    • 我需要打破字符串以计算所有行的 (TF-IDF) 术语,每一行都是一个文档
    • 啊,好的。所有文档的总词汇量是多少?
    【解决方案2】:

    memory error 在这里出现,因为即使您逐行读取文件,您也将其内容存储在字典 docDict 中,因此存储在内存中。

    我不知道你打算用这本字典做什么,但我建议在你阅读每一行之后执行该过程,然后将结果存储在一个变量中(如果过程压缩很多),或直接在文件或数据库中。

    希望我能帮上忙!再见!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-15
      • 2011-12-08
      • 2012-07-05
      • 2022-01-18
      • 2022-06-15
      • 1970-01-01
      • 2020-03-19
      • 1970-01-01
      相关资源
      最近更新 更多