0

我想要一个包含不同数量 n 个对象的类,这些对象可以很容易地作为一个组进行迭代,每个对象成员都有一个大列表(20 多个)影响类方法的单独修改的变量。在我开始学习 OOP 之前,我会创建一个二维数组并将变量值加载到每一行中,对应于每个对象,然后根据需要追加/删除行。这仍然是一个好的解决方案吗?有更好的解决方案吗?

同样,在这种情况下,我更感兴趣的是推动处理器性能,而不是保留抽象和模块化等。在这方面,我对数据容器最终被读入 L1 缓存的方式以及如何确保我感到非常困惑。不要导致页面效率低下或缓存未命中。例如,如果我有一个 128 kb 的缓存,我假设整个容器都应该适合这个缓存以提高效率,对吗?

4

1 回答 1

0

根据Agner Fog 的优化手册,C++ 标准模板库的效率相当低,因为它大量使用了动态内存分配。但是,固定大小的数组大于必要的大小(例如,因为在编译时不知道所需的大小)也可能对性能不利,因为较大的大小意味着它不能轻易地放入缓存中。在这种情况下,STL 的动态内存分配可以表现得更好。

通常,最好将数据存储在连续内存中。您可以为此使用固定大小的数组或 an std::vector。但是,在使用之前std::vector,您应该std::vector::reserve()出于性能原因调用,这样就不必过于频繁地重新分配内存。如果您过于频繁地重新分配,堆可能会变得碎片化,这也对缓存性能不利。

理想情况下,您正在处理的数据将完全适合 1 级数据缓存(在现代桌面处理器上约为 32 KB)。但是,即使它不适合,二级缓存也要大得多(大约 512 KB),而三级缓存有几兆字节。更高级别的缓存仍然比从主内存读取要快得多。

最好是您的内存访问模式是可预测的,这样硬件预取器才能最好地工作。硬件预取器最容易预测顺序内存访问。

如果您多次访问相同的数据并且数据小到可以保存在缓存中,那么 CPU 缓存的效果最好。但是,即使数据只使用一次,CPU 缓存仍然可以通过使用prefetching使内存访问更快。

如果发生缓存未命中

  1. 第一次访问数据并且硬件预取器无法及时预测和预取所需的内存地址,或者
  2. 数据不再被缓存,因为缓存必须为其他数据腾出空间,因为数据太大而无法放入缓存。

除了尝试提前预测所需内存地址的硬件预取器(这是自动的)之外,程序员还可以显式地发出软件预取。但是,从我所读到的内容来看,除非在非常特殊的情况下,否则很难通过这样做来获得显着的性能提升。

于 2020-01-07T12:21:31.627 回答