为什么C++二维vector初始化耗时比一维vector高20倍?
性能差异核心原因
二者虽然存储的float总数量都是100万,但实际初始化的开销完全不在一个量级,核心差异如下:
- 内存分配次数差了100万倍
一维初始化代码vector<float> b(1000000);全程只需要1次堆内存分配:直接申请一块连续的、能容纳100万个float的内存块即可。
而二维初始化代码vector<vector<float>>a(1000000,vector<float>(1));需要1 + 1000000次堆内存分配:外层vector先申请1块能存100万个vector<float>对象的内存,之后每个内层的vector<float>都要单独申请1块存1个float的内存。堆内存分配本身是高开销操作,需要处理内存对齐、分配器锁、空闲块检索等逻辑,百万次分配的开销会直接占据大部分耗时。 - 额外的对象管理开销
每个vector实例本身都要存储3个管理指针(起始地址、使用结束地址、容量结束地址),64位系统下单个vector实例就占24字节。二维vector的外层要存储100万个vector实例,光这部分就有24MB的初始化开销,而一维vector只需要维护3个指针、共24字节的管理数据。 - 额外的拷贝构造开销
你用到的vector(size_t n, const T& val)构造函数,会把入参的val拷贝构造n次赋值给每个元素。二维场景下需要做100万次vector<float>的拷贝构造,每次拷贝都要走vector的拷贝逻辑、分配内存、复制元素,而一维场景只需要做100万次float的初始化,开销差距极大。 - CPU缓存命中率差异
一维vector的所有float数据是连续存储的,初始化时CPU缓存命中率接近100%,执行效率极高。而二维vector的每个float分散在100万个独立的堆内存块中,地址不连续,初始化时缓存命中率极低,进一步拖慢执行速度。
关闭优化后差距拉大的原因
编译开启优化时,编译器会把vector的很多操作做inline处理,甚至可以消掉部分不必要的重复逻辑,一定程度上降低二维场景的额外开销。关闭优化后,所有vector的构造、内存分配、拷贝逻辑都是实打实的函数调用,百万次函数调用的开销会被完全释放,因此二者的耗时差距会进一步拉大。
内容的提问来源于stack exchange,提问作者dan gha
相关产品推荐
相关产品推荐

