3

这是我的结构

struct Node
{
 int chrN;
 long int pos;
 int nbp;
 string Ref;
 string Alt;
};

填充我通过文件读取的结构并将我的兴趣变量解析为结构,然后将其推回向量。问题是,大约有 2 亿个项目,我应该将所有项目都保存在内存中(以备后续步骤)!但是程序在以 bad_allocation 错误推回 5000 万个节点后终止。

terminate called after throwing an instance of 'std::bad_alloc'
what():  std::bad_alloc

四处寻找让我觉得我没有记忆了!但 top 的输出显示 %48 (终止发生时)

可能有用的其他信息:我将堆栈限制设置为 unlimit,并且我使用的是 Ubuntu x86_64 x86_64 x86_64 GNU/Linux 和 4Gb RAM。

任何帮助都将是最受欢迎的。

更新:

第一次从向量切换到列表,然后将每个 ~500Mb 存储在文件中并为它们编制索引以供进一步分析。

4

5 回答 5

4

向量存储是连续的,在这种情况下,需要 200 mio * struct 字节的大小。对于结构中的每个字符串,可能需要另一个小型分配来保存该字符串。总之,这不适合您的可用地址空间,并且没有(非压缩)数据结构可以解决这个问题。

向量通常会以指数方式增长其支持容量(这会分摊成本push_back)。因此,当您的程序已经使用了大约一半的可用地址空间时,向量可能试图将其大小增加一倍(或增加 50%),然后导致bad_alloc它并没有释放前一个缓冲区,所以最终的内存似乎只有48%。

于 2013-09-26T14:13:07.807 回答
2

该节点结构最多消耗 44 个字节,加上实际的字符串缓冲区。4 GB 中不可能有 2 亿个。

您不需要一次将整个数据集保存在内存中。

于 2013-09-26T14:13:13.783 回答
0

由于向量必须将所有元素存储在连续内存中,因此在消耗全部可用 RAM 之前,您更有可能耗尽内存。

尝试使用 std::list 并查看它是否可以保留您的所有项目。您将无法随机访问元素,但这是您最有可能必须处理的权衡。

std::list 可以更好地利用 RAM 的空闲片段,因为与向量不同,它不会尝试存储彼此相邻的元素。

于 2013-09-26T14:08:47.530 回答
0

根据数据类型的大小,我猜,您使用的结构至少有 4+8+4+2+2=20 字节长。如果您有 200 000 000 个数据字段,这将是大约 3.8 GB 的数据。不确定您从顶部读取的内容,但这已接近您的内存限制。

正如 LatencyMachine 所指出的,这些项目必须在一个连续的内存块中,这很困难(字符串内存可以在其他地方,但我总结的两个字节必须在向量中)。

它可能有助于以正确的大小初始化向量以避免重新分配。

于 2013-09-26T14:13:28.247 回答
0

如果你看看这段代码:

#include <iostream>
using namespace std;
struct Node
{
 int chrN;
 long int pos;
 int nbp;
 string Ref;
 string Alt;
};
int main() {
    // your code goes here
    cout << sizeof(Node) << endl;
    return 0;
}

它在ideone上产生的结果你会发现,即使字符串是空的,并且在 32 位计算机上,你的结构的大小也是 20。因此200 * 10^6,这个大小正好是 4GB。你不能希望只为你拥有整个记忆。所以你的程序会疯狂地使用虚拟内存。你必须想办法只存储部分元素,否则你的程序会遇到很大的麻烦。

于 2013-09-26T14:14:15.060 回答