分配一个大的多维向量会导致内存 "overshoot"

Allocating a large multidimensional vector causes memory "overshoot"

我在使用大型多维 std::vector 变量时观察到意外行为。特别是,当我分配一个大尺寸的 4 维向量时,使用内存分析器可以看出,我的任务很快使用了比变量所需的内存更多的内存。

重现此行为的 MWE 如下:

#include <vector>
#include <iostream>

int main(int argc, char *argv[]){

    getchar();
    std::vector<std::vector<std::vector<std::vector<int64_t>>>> F(1, std::vector<std::vector<std::vector<int64_t>>>(15, std::vector<std::vector<int64_t>>(256, std::vector<int64_t>(100000, 0))));
    getchar();
}

下图显示了任务使用的内存。阵列的大小大约需要 3GB,但内存使用量很快就会超过 6GB。请注意,向量的最后一个维度是最大的,这意味着向量 class 的内存开销相对较小。

这是在 64 位系统上的 Manjaro 下观察到的,使用 g++(gcc 版本 11.1.0 (GCC))编译。我使用 psrecord 来记录内存使用情况。有趣的是,我无法为低维向量重现相同的行为。即使我只删除第一个维度(大小为 1),我也无法在我的系统上重现这个过冲。

有谁知道这是从哪里来的,或者是否可以避免(不使用大的一维向量)?这样做的主要问题是我的操作接近系统提供的最大内存,这意味着短暂的超调会导致内存交换。

如果有任何想法和评论,我将很高兴。提前致谢。

这可能是由不同的原因引起的,例如 return未使用智能指针(这可能会导致复制)。

但是在您的特定情况下,您将某些内容传递给 F 变量的构造函数(无论如何),这需要额外的内存直到构造函数 returns.

哦!另一个可能的原因是,(非)智能矢量实现应该保留比需要更多的部分(以防万一,以加快以后的附加速度)。

示例:

以下是修复 OP 问题的内容:

#include <vector>
#include <iostream>

int main(int argc, char *argv[]){
    getchar();

    std::vector<std::vector<std::vector<std::vector<int64_t>>>> F(
        1, std::vector<std::vector<std::vector<int64_t>>>(15, std::vector<std::vector<int64_t>>(256))
    );
    for (int i = 0; i < 15; i++)
        for (int j = 0; j < 256; j++)
            F[0][i][j] = std::vector<int64_t>(100000, 0);

    getchar();
}

除了@amon、@NathanOliver 和@Top-Master 的评论解释了问题的根源,我将提供一个解决问题的代码示例。

#include <vector>
#include <iostream>

int main(int argc, char *argv[]){

    getchar();
    std::vector<std::vector<std::vector<std::vector<int64_t>>>> F(1, std::vector<std::vector<std::vector<int64_t>>>(15, std::vector<std::vector<int64_t>>(256)));
    for (int i=0; i<15; i++) for (int j=0; j<256; j++) F[0][i][j] = std::vector<int64_t>(100000, 0);
    getchar();
}