使用巨大的向量在C ++程序中冻结

时间:2013-12-09 16:15:19

标签: c++ vector size freeze

我遇到了C ++程序的问题。我认为这是一个记忆问题。 在我的程序中,我习惯于创建一些巨大的std :: vector(我使用reserve来分配一些内存)。矢量大小为1 000 000,没关系,但如果我增加这个数字(大约一千万),我的程序将冻结我的电脑,除了等待崩溃(或者如果我很幸运,程序结束)我什么都不做。我的向量包含一个名为Point的结构,它包含一个double的向量。

我用valgrind检查是否缺少内存。但不是。根据它,没有问题。也许不建议使用对象矢量?或者可能有一些系统参数要检查或什么?或者简单地说,向量对于计算机而言太大了?

您如何看待这个?

2 个答案:

答案 0 :(得分:4)

声明

请注意,这个答案假定您的机器有一些事情;确切的内存使用和错误可能取决于您的环境。当然,当你不在2d-point上计算时,它会更容易崩溃,但是4d点,例如计算机图形学中常见的,或者甚至更大的点用于其他数字目的。

关于您的问题

分配的内存相当多:

#include <iostream>
#include <vector>
struct Point {
    std::vector<double> coords;
};
int main () {
    std::cout << sizeof(Point) << std::endl;
}

这会打印12,这是空Point的字节大小。如果您有二维点,则为每个元素添加另一个2*sizeof(double)=8,即现在每Point总共有20个字节。

拥有数百万个元素,您需要200万个字节的数据,例如对于2000万个元素,您需要400万个字节。虽然这不超过std::vector的最大索引,但操作系统可能没有那么多连续的内存可供您使用。

此外,您的vector内存需要经常复制才能增长。这种情况发生在您push_back时,所以当您已经拥有400MiB vector时,在下一个push_back您可能拥有旧版本的vector,再加上新版本std::vector分配400MiB * X内存,因此您可以轻松超过1000MiB临时等等。

优化(高级别; 首选

您是否需要一直存储数据?你能使用不需要那么多存储的类似算法吗?您可以重构代码以减少存储空间吗?当你知道它需要一些时间直到你再次需要它时,你可以核实一些数据吗?

优化(低级别)

如果您在创建外部向量之前知道元素的数量,请使用vector<Foo> foo(12) // initialize have 12 elements 构造函数,您可以告诉它初始大小:

double

当然,您可以优化大量内存;例如如果你知道你总是只有2d点,那么只需要两个double作为成员:20个字节 - &gt; 16个字节。如果您不需要float的精度,请使用// struct Point { std::vector<double> coords; }; <-- old struct Point { float x, y; }; // <-- new :16字节 - &gt; 8个字节。这是$ 2/5 $的优化:

std::deque

如果这仍然不够,ad-hoc解决方案可能是struct Point { signed char x, y; }; // <-- or even this? examine a proper type struct Point { short x_index, y_index; }; ,或另一个非连续容器:没有时间内存“加倍”,因为不需要调整大小;也不需要操作系统找到你这样连续的内存块。

您还可以使用压缩机制,索引数据或定点数。但这取决于你的具体情况。

{{1}}

答案 1 :(得分:1)

没有看到你的代码,这只是推测,但我怀疑它在很大程度上是由于你试图分配大量连续的内存。 std::vector保证在连续内存中,因此如果您尝试分配大量空间,操作系统必须尝试查找可以使用的大块内存块。对于2MB这可能不是问题,但是如果你突然想要分配200MB或2GB的连续内存......

此外,无论何时向向量添加新元素并强制调整大小,都必须将所有现有元素复制到分配的新空间中。如果您有900万个元素并且添加9,000,001元素需要调整大小,那么必须移动900万个元素。随着矢量变大,此复制时间会更长。

请尝试使用std::deque。它基本上会分配页面(这将是连续的),但每个页面都可以分配到任何适合的位置。