C++ C++;创建巨大的向量

C++ C++;创建巨大的向量,c++,c++11,memory,memory-management,bad-alloc,C++,C++11,Memory,Memory Management,Bad Alloc,对于我试图运行的进程,我需要一个std::vector的std::tuple。我现在正在做的测试应该创建一个47614527250(约470亿)元组的向量,但实际上在创建时崩溃,抛出一个'std::bad_alloc'实例后调用了错误terminate。我的目标是将这个脚本与一个大约两倍大小的向量一起使用。代码如下: arc_vector = std::vector<std::tuple<long unsigned int, long unsigned int>>(arc

对于我试图运行的进程,我需要一个
std::vector
std::tuple
。我现在正在做的测试应该创建一个47614527250(约470亿)元组的向量,但实际上在创建时崩溃,抛出一个'std::bad_alloc'实例后调用了错误
terminate
。我的目标是将这个脚本与一个大约两倍大小的向量一起使用。代码如下:

arc_vector = std::vector<std::tuple<long unsigned int, long unsigned int>>(arcs);
arc_vector=std::vector(弧);
其中,
arcs
是带有引用值的
长无符号int


在这种情况下,我可以增加内存大小吗?这个脚本运行在一台40核的机器上,内存大约为200GB,所以我知道内存本身不是问题

您可能有一台拥有大量内存的机器,但问题是您需要该内存是连续的

即使使用内存虚拟化,这也不太可能


对于这些数据量,您需要使用不同的存储容器。您可以根据细分数据的向量链表、指向元组细分向量的指针向量滚动自己的数据,或者找到一个已经构建了这种结构的库。

470亿元组乘以16字节每个元组是7800亿字节,约760 gb。您的计算机的内存不足所需内存的1/3,因此您确实需要另一种方法,而不管程序崩溃的原因是什么

我可以给你一个建议,使用一个1TB的内存映射文件来存储这个数组,如果你真的需要使用一个向量作为接口,你可以为它编写一个使用映射内存的自定义分配器。这将以一种准透明的方式解决主内存不足的问题。如果您的接口需要使用标准分配器的标准向量,那么最好重新设计它


另一点需要补充的是,检查运行进程的用户的
ulimit
值,因为它的虚拟内存限制可能比760 gb更严格。

您确定您的操作系统允许连续分配470亿个元素吗?即使操作系统允许,你确定内存在一个地方有那么多的可用空间吗?(例外情况表明答案是否定的)您需要
sizeof(std::tuple)
乘以470亿字节的连续可用内存。在64位机器上(64位
),作为一个单独的可用块,内存远远超过750 GiB。根据我的计算,您的机器需要大约800 GB的RAM。总之,您可能需要重新考虑您的算法以及同时将所有元素存储在内存中的需要。@gioaudino如果您的旧库API需要一个包含近千亿元素的数组,那么我怀疑最可能的情况是您误解了该库的使用方式。您正在为一个旧库构建一个
std::tuple
向量作为参数的事实也是可疑的。那么
std::deque
呢?@FrançoisAndrieux:我会担心元素访问时间。我不认为连续内存是一个问题,因为您永远不会在一个页面中分配750G。操作系统可能需要拆分为多个页面,这样地址在虚拟地址空间中是连续的,而在真实地址空间中不是连续的。为什么您认为连续内存是个问题?在64位机器上,地址空间非常大。即使操作系统不使用整个64位,像通常的48位地址空间一样已经足够了。对不起,我不明白你所说的“现实对我来说已经足够好了”是什么意思。OP没有足够的内存,因此OS拒绝分配。在我看来,连续性在这里并不重要。正如我所说,一个48位的地址空间很容易就能容纳1TB的缓冲区。这是一个不错的解决方案,但它可能会非常慢。。。根据程序所做的,它可能只是磁盘上已有数据的简单拷贝。在这种情况下,直接在输入文件中修改单个值可能是更好的解决方案。@Sander速度是否慢完全取决于算法的功能。请注意,由于您的工作集比主内存大,因此您仍然需要一些磁盘访问权限。如果您的算法可以以流式方式执行,或者以其他一些可预测的内存访问模式执行,那么通过显式实现该算法,您可能会获得更好的结果,但在大多数情况下,您最终会实现磁盘数据结构的糟糕缓存机制,操作系统可能会做得更好:内存映射与流IOS相比非常快,或者只是添加必要的交换量,可以非常容易地进行尝试。