机器学习项目中20000×20000矩阵:静态数组与vector嵌套内存差异咨询
为什么嵌套vector的内存占用远高于静态数组?
咱们先算个理论值:20000×20000的double矩阵,每个double占8字节,纯数据的内存应该是 20000*20000*8 = 3200000000 字节,差不多2.98GB。结合你的代码和观察到的现象,来拆解背后的原因:
1. 嵌套vector的额外开销(非主要差距来源)
嵌套的vector<vector<double>>会带来两层容器级的开销:
- 外层vector本身是个对象,在64位系统下,它包含3个指针(指向数据起始、末尾、容量上限),占24字节。
- 每个内层
vector<double>也是独立的容器对象,同样占24字节,20000个加起来也就468KB左右——这点开销完全解释不了1.5GB的差距,真正的问题出在内存分配机制上。
2. 静态数组的“写时复制”延迟分配
你的静态数组代码:
static double distanceMatrix[20000][20000] = {0};
因为加了static,这个数组存在静态存储区,而且你用{0}初始化,编译器会把整个数组置零。这里操作系统做了个优化:它不会立刻给数组分配全部物理内存,而是把数组映射到一个共享的零页——这是系统维护的只读内存页,所有全零的静态数据都可以共享它。
只有当你真正往数组里写数据的时候,操作系统才会为对应位置分配物理内存(写时复制机制)。你的循环只填充了i<j的部分(刚好一半元素),所以操作系统只会为这部分分配物理内存,总占用就约为3GB的一半,也就是你看到的1.57GB,而且内存会随着循环逐步增长——每写一块数据,就分配对应的物理页。
3. 嵌套vector的立即物理内存分配
再看你的vector代码:
vector<vector<double>> distanceMatrix(20000, vector<double>(20000));
创建内层vector<double>(20000)时,vector会立刻从堆上分配内存。堆内存是可读写的,操作系统没法用共享零页的方式优化,必须为每个内层vector分配实际的物理内存页。所以在循环开始前,所有物理内存已经被占满了,加上每个内层vector内存块的微小页对齐浪费,总占用就接近3.06GB,和理论值一致。
小测试与优化建议
- 如果你把静态数组的初始化去掉(
static double distanceMatrix[20000][20000];),数组内容是未定义的,操作系统会在启动时就分配全部物理内存,此时它的内存占用会和vector版本差不多。 - 如果想让vector版本也接近静态数组的内存效率,可以用单个vector模拟二维数组:
这种方式是连续的一块内存,没有内层vector的开销,要是初始化全零的话,也可能享受到零页的写时复制优化。vector<double> distanceMatrix(20000*20000); // 用 distanceMatrix[i*20000 + j] 代替 distanceMatrix[i][j]
内容的提问来源于stack exchange,提问作者Bahadır
相关产品推荐
相关产品推荐

