我遇到了C ++程序的问题。我认为这是一个记忆问题。 在我的程序中,我习惯于创建一些巨大的std :: vector(我使用reserve来分配一些内存)。矢量大小为1 000 000,没关系,但如果我增加这个数字(大约一千万),我的程序将冻结我的电脑,除了等待崩溃(或者如果我很幸运,程序结束)我什么都不做。我的向量包含一个名为Point的结构,它包含一个double的向量。
我用valgrind检查是否缺少内存。但不是。根据它,没有问题。也许不建议使用对象矢量?或者可能有一些系统参数要检查或什么?或者简单地说,向量对于计算机而言太大了?
您如何看待这个?
答案 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
。它基本上会分配页面(这将是连续的),但每个页面都可以分配到任何适合的位置。