计算向量的向量大小(以字节为单位)

Calculating size of vector of vectors in bytes

typedef vector<vector<short>> Mshort;
typedef vector<vector<int>> Mint;

Mshort mshort(1 << 20, vector<short>(20, -1)); // Xcode shows 73MB 
Mint mint(1 << 20, vector<int>(20, -1)); // Xcode shows 105MB

short使用2字节,int使用4字节;请注意 1 << 20 = 2^20;

我正在尝试提前(在纸面上)计算内存使用量,但我无法计算。

sizeof(vector<>) // = 24 //no matter what type
sizeof(int) // = 4
sizeof(short) // = 2

我不明白:mint 应该是 mshort 的两倍,但事实并非如此。当 运行 程序只有 mshort 初始化时 Xcode 显示 73MB 的内存使用; mint 105MB;

mshort.size() * mshort[0].size() * sizeof(short) * sizeof(vector<short>) // = 1006632960
mint.size() * min[0].size() * sizeof(int) * sizeof(vector<int>) // = 2013265920

//no need to use .capacity() because I fill vectors with -1
1006632960 * 2 = 2013265920

如何计算 2d std::vector 或 2d std::array 使用多少 space RAM。

我知道前面的尺寸,每行的列数相同。

向量的向量的内存使用量将是例如

// the size of the data...
mshort.size() * mshort[0].size() * sizeof(short) +

// the size of the inner vector objects...
mshort.size() * sizeof mshort[0] +

// the size of the outer vector object...
// (this is ostensibly on the stack, given your code)
sizeof mshort +

// dynamic allocation overheads
overheads

动态分配开销是因为 vector 在内部 new 存储元素的内存,并且出于速度原因,它们可能有固定大小的内存区域池等待新请求,所以如果 vector 有效地执行 new short[20] - 数据需要 40 个字节 - 它可能以例如结束。 48 或 64。实现实际上可能需要使用一些额外的内存来存储数组大小,但对于 shortint 来说,在 delete[] 期间不需要循环调用析构函数的元素,所以一个好的实现将避免分配和无操作破坏行为。

虽然任何给定向量的实际数据元素在内存中都是连续的,因此如果您想减少开销,您可以更改代码以使用更少、更大的 vector。例如,将 vector(1 << 20) * 20 一起使用的开销可以忽略不计 - 然后您可以访问 [i * 20 + j] 而不是访问 [i][j] - 您可以编写一个简单的 class 包装vector 为您完成此操作,最简单的方法是使用 v(i, j) 符号...

inline short& operator()(size_t i, size_t j) { return v_[i * 20 + j]; }
inline short operator()(size_t i, size_t j) const { return v_[i * 20 + j]; }

...尽管您可以通过让 v.operator[] return 一个可以用 [] 进一步索引的代理对象来支持 v[i][j]。我敢肯定,如果您在 SO 中搜索有关多维数组的问题,将会有一些示例 - 我想我自己可能已经发布过一次这样的代码。

想要 vector<vector<x>> 的主要原因是内部 vector 的长度不同。

假设 glibc malloc: 每个内存块将为内存块header分配额外的8-16字节(2size_t)。对于 64 位系统,它将是 16 个字节。 见代码: https://github.com/sploitfun/lsploits/blob/master/glibc/malloc/malloc.c#L1110

chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |             Size of previous chunk, if allocated            | |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |             Size of chunk, in bytes                       |M|P|
  mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |             User data starts here...                          .
    .                                                               .
    .             (malloc_usable_size() bytes)                      .
    .                                                               |

当每行添加 16 个字节时,它给了我大约 83886080。

26+16+ mshort.size(1048576) * (mshort[0].size(20)*sizeof(short(2)) + sizeof(vector(26))+header (16))

它给我大约 125829120 的整数。

但后来我重新计算了你的数字,看起来你是在 32 位...

  • 短 75497472 即 ~73M
  • long 117440512 即 ~112M

看起来与报告的非常接近。

使用容量而不是大小来获取#items 数量,即使它们与您的情况相同。

分配单个矢量大小行*列将为您节省 header*1048576 字节。

你的计算mshort.size() * mshort[0].size() * sizeof(short) * sizeof(vector<short>) // = 1006632960完全错误。根据您的计算,mshort 需要 1006632960,即 960MiB,这是不正确的。

让我们忽略 libc 的开销,只关注 std::vector<> 的大小: mshortvector1^20 项,每个 vector<short> 有 20 个项。 所以大小应该是:

mshort.size() * mshort[0].size() * sizeof(short) // Size of all short values + mshort.size() * sizeof(vector<short>) // Size of 1^20 vector<short> + sizeof(mshort) // Size of mshort itself, which can be ignored as overhead

计算出的大小为64MiB.

同mint,计算大小为104MiB.

所以 mint 只是 不是 mshort 的两倍大小。