根据Agner Fog 的优化手册,C++ 标准模板库的效率相当低,因为它大量使用了动态内存分配。但是,固定大小的数组大于必要的大小(例如,因为在编译时不知道所需的大小)也可能对性能不利,因为较大的大小意味着它不能轻易地放入缓存中。在这种情况下,STL 的动态内存分配可以表现得更好。
通常,最好将数据存储在连续内存中。您可以为此使用固定大小的数组或 an std::vector
。但是,在使用之前std::vector
,您应该std::vector::reserve()
出于性能原因调用,这样就不必过于频繁地重新分配内存。如果您过于频繁地重新分配,堆可能会变得碎片化,这也对缓存性能不利。
理想情况下,您正在处理的数据将完全适合 1 级数据缓存(在现代桌面处理器上约为 32 KB)。但是,即使它不适合,二级缓存也要大得多(大约 512 KB),而三级缓存有几兆字节。更高级别的缓存仍然比从主内存读取要快得多。
最好是您的内存访问模式是可预测的,这样硬件预取器才能最好地工作。硬件预取器最容易预测顺序内存访问。
如果您多次访问相同的数据并且数据小到可以保存在缓存中,那么 CPU 缓存的效果最好。但是,即使数据只使用一次,CPU 缓存仍然可以通过使用prefetching使内存访问更快。
如果发生缓存未命中
- 第一次访问数据并且硬件预取器无法及时预测和预取所需的内存地址,或者
- 数据不再被缓存,因为缓存必须为其他数据腾出空间,因为数据太大而无法放入缓存。
除了尝试提前预测所需内存地址的硬件预取器(这是自动的)之外,程序员还可以显式地发出软件预取。但是,从我所读到的内容来看,除非在非常特殊的情况下,否则很难通过这样做来获得显着的性能提升。