在C++程序中使用巨大的矢量进行冻结
Freeze in C++ program using huge vector
我的C++程序有问题。我认为这是记忆力的问题。在我的程序中,我习惯于创建一些巨大的std::vector(我使用reserve来分配一些内存)。向量大小为1000 000,这是可以的,但如果我增加这个数字(大约1000万),我的程序将冻结我的电脑,我只能等待崩溃(或者如果幸运的话,程序结束)。我的向量包含一个叫做点的结构,它包含一个双向量。
我用valgrind检查是否有记忆力不足。但没有。根据它的说法,没有问题。也许不建议使用对象向量?或者可能有一些系统参数需要检查或其他什么?或者简单地说,矢量对计算机来说太大了?
你对此怎么看?
免责声明
请注意,这个答案假设了关于您的机器的一些事情;确切的内存使用情况和潜在的错误取决于您的环境。当然,当你不计算2d点时,崩溃会更容易,但例如4d点,这在计算机图形学中很常见,或者更大的点用于其他数字目的。
关于你的问题
这是相当多的内存分配:
#include <iostream>
#include <vector>
struct Point {
std::vector<double> coords;
};
int main () {
std::cout << sizeof(Point) << std::endl;
}
这将打印12
,它是空Point
的字节大小。如果您有2维点,请为每个元素添加另一个2*sizeof(double)=8
,即现在每个Point
总共有20个字节。
对于1000万个元素,您请求200万个字节的数据,例如对于2000万个元素来说,您请求4亿个字节。虽然这不会超过std::vector
的最大索引,但操作系统可能没有那么多可用的连续内存。
此外,vector
的内存需要经常复制才能增长。例如,当您push_back
时就会发生这种情况,因此当您已经有一个400MiB的vector
时,在下一个push_back
时,您可能会有旧版本的vector
,再加上新分配的400MiB*X内存,因此您可能很容易超过1000MiB的临时内存,等等。
优化(高级;首选)
您是否需要始终存储数据?你能使用一种不需要那么多存储的类似算法吗?你能重构你的代码以减少存储空间吗?当你知道需要一段时间才能再次需要数据时,你能把一些数据核心化吗?
优化(低级别)
如果在创建外部向量之前知道元素的数量,请使用std::vector
构造函数,它可以告诉您初始大小:
vector<Foo> foo(12) // initialize have 12 elements
当然,你可以优化很多内存;例如,如果你知道你总是只有2d点,那么只需要有两个double
作为成员:20字节->16字节。当您并不真正需要double
的精度时,请使用float
:16字节->8字节。这是对$2/5$的优化:
// struct Point { std::vector<double> coords; }; <-- old
struct Point { float x, y; }; // <-- new
如果这仍然不够,则ad-hoc解决方案可以是std::deque
,或者另一个非连续容器:无临时存储器";加倍";因为不需要调整大小;操作系统也不需要为您找到这样的连续内存块。
您还可以使用压缩机制、索引数据或固定点号。但这取决于你的具体情况。
struct Point { signed char x, y; }; // <-- or even this? examine a proper type
struct Point { short x_index, y_index; };
在没有看到您的代码的情况下,这只是猜测,但我怀疑这在很大程度上是由于您试图分配大量连续的内存。std::vector
保证在连续内存中,因此如果您试图分配大量空间,操作系统必须尝试找到一块可以使用的大内存。对于2MB来说,这可能不是问题,但如果您突然尝试分配200MB或2GB的连续内存。。。
此外,每当您向向量中添加新元素并强制调整其大小时,所有现有元素都必须复制到分配的新空间中。如果您有900万个元素,并且添加9000001元素需要调整大小,则必须移动900万个图元。矢量越大,复制时间就越长。
请尝试使用std::deque
。它基本上会分配页面(将是连续的),但每个页面都可以分配到任何合适的位置。
- 在linux上调试巨大的C++项目
- WIN32:C++,为什么在WM_CLOSE上调用Messagebox函数程序正在冻结
- GCC 和 Clang 代码性能的巨大差异
- Win32 发送输入鼠标移动滞后并冻结
- ImGui 在单击按钮后冻结
- 找到一种有效的方法,在 2 个巨大的缓冲区上执行 MAX,每字节字节
- QWidget UI 在使用 QQuickWidget 时冻结
- 如何防止 std::thread 在 QT 中冻结 GUI?
- Adafruit 羽毛RFM69HCW在使用过程中会冻结,需要硬重置
- MFC/C++ ComboBox:禁用下拉列表关闭和打开(UI 冻结)的绘制
- 将数字提高到一个巨大的指数
- 巨大的内存分配:堆栈与堆
- 模板总和函数冻结字符
- 程序在对mouse_event的 Windows API 调用中冻结
- MSYS2 上的 CMake 冻结
- 初始化不是整数的巨大常量多维数组的最佳方法是什么?
- 在 v8 JavaScript 中重复调用C++是否有巨大的开销?
- 在C++程序中使用巨大的矢量进行冻结
- 调试冻结计算机的巨大内存泄漏(C++)
- C++程序在访问一个巨大的数组时会冻结