C++向量内存耗尽。

6
我有一个非常大的向量(数百万个1024字节的条目)。我超出了向量的最大尺寸(会得到一个内存分配异常)。我正在对项向量进行递归操作,需要访问向量中的其他元素。这些操作需要快速完成。我试图避免为了速度而写入磁盘。是否有其他不需要写入磁盘的存储数据的方法?如果必须将数据写入磁盘,最理想的方法是什么?
编辑一些更多细节。
我对数据集执行的操作是基于向量中的其他数据点递归生成字符串。读入数据时,数据已排序。数据集范围从50,000到50,000,0000。

5
如果没有更多关于你数据的信息,我们无法发表任何意见。 - NPE
3
你所做的事情是否需要连续的内存?如果不需要,一个简单的改变是使用std::deque代替;这应该能让你在耗尽内存之前存储更多的元素。 - Praetorian
3
大多数 std::vector 的实现采用容量加倍的重新分配策略,这意味着如果您经常扩展向量的大小,它可能会使用比存储可寻址元素所需的更多存储空间。 - Charles Salvia
1
是的,数据需要连续。感谢您的建议。 - user2174896
4
32位的内存空间,每个数据块大小为1024字节,意味着理论上的最大容量为2^22个项目(实际容量要远小于此,因为不是所有的内存空间都用于这一个容器)。这仅仅只有420万个元素。在32位操作系统上,你想要一个包含“数百万”个1024字节元素的连续内存缓冲区 - 答案是“不行,你做不到”。如果放松一些限制,就可以解决这个问题。那么,为什么需要连续的内存空间呢? - Yakk - Adam Nevraumont
显示剩余8条评论
4个回答

10

解决这个问题最简单的方法是使用STXXL。它是STL的重新实现,用于大型结构,在数据超出内存限制时,能够透明地将数据写入磁盘。


4
如果数据必须是连续的,STXXL怎样帮助?任何写入磁盘的操作(透明或非透明)都会破坏数据的连续性。 - Yakk - Adam Nevraumont
@Yakk,它并不是真正的连续存储,它只是呈现了与std::vector相同的接口。问题并没有要求它是连续的,或者至少在我回答时没有这样要求。 - Dirk Holsopple
1
@DirkHolsopple 是的,提问者在问题的评论中深入添加了该限制。 - user334856
8
@Yakk,也许“我需要无限连续的内存”不是一个合理的要求。 - Charles Salvia

3

根据评论中阐述的内容,您提出的问题无法得到解决。

您要求在32位系统上拥有一个大小为1024的连续内存缓冲区,其中包含5000万个条目。

32位系统只有4294967296字节的可寻址内存。您正在请求51200000000字节的可寻址内存,即您系统上内存地址空间的11.9倍。

如果您不需要数据是连续的且可寻址的内存,如果您不要求所有数据一次性全部在内存中,或者如果您放宽了其他要求,则可能会有解决方案。例如,一些操作系统通过某些hacky接口或其他方式公开访问与RAM相对应的非内存空间的值(在8GB Windows系统中有方法使用超过4GB的总RAM)。

但是,按照您所述,答案是否定的。


我就是这么想的。谢谢。 - user2174896
1
@user2174896,我的回答的意思是“你问错了问题”,而不是“你无法解决实际问题”。我强烈怀疑你的实际问题是“32位操作系统上51200000000字节的连续内存空间”。 - Yakk - Adam Nevraumont

0
由于您的数据必须是连续的,并且您知道需要存储多少个元素,只需创建一个 std::vector 并使用 reserve() 函数尝试获取所需大小的连续内存块。
存储向量的开销非常小(只有几个指针来管理开始和结束)。这是您能够做到的最好的。
如果失败了:
  • 在机器上添加更多内存(如果您遇到 addressing 或实现限制,则实际上可能没有帮助)
  • 切换到原始数组
  • 找到一种方法来减少你的元素的大小
  • 尝试找到一种可以分成小块处理问题的解决方案

1
在现代操作系统中,将更多的内存添加到计算机上对于vector的最大大小没有任何作用,假设用户已经允许足够的虚拟内存。分配是关于消耗地址空间,而不是内存。即使如此,操作系统可以轻松地分配比它们拥有的虚拟内存更多的地址空间,并且只有在实际修改内存时才会失败。 - Yakk - Adam Nevraumont
这正是我想到的。谢谢。 - user2174896

-1

这是1GB的内存(1024KB * 10 ^ 6 = 1MB * 10 ^ 3 = 1GB)。理想情况下,对于32位机器,最多可以执行4GB的内存操作。 为了回答您的问题,请首先尝试使用普通的malloc()调用并分配1GB的内存。这应该可以无错误完成。 此外,请粘贴在使用向量时收到的确切错误消息。


在问题中,OP提供的唯一有用的信息就是他看到的错误 - bad memory alloc exception,也称为std::bad_alloc - Praetorian
使用 malloc 就是一个答案 :) - Shehbaz Jaffer
1
这是一个错误的答案。问题中说的是百万,不只是一百万。即使假设只有200-300万,也不能保证32位机器可以分配2-3GB的连续地址空间。一些地址空间将用于内核、共享库、堆栈等。 - Dirk Holsopple
2
问题还说了“百万”个1024字节。 - user334856

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接