面向数据的设计;如何在 C++ 中优化数据结构以提高性能?
Data Orientated Design; how do I optimize a data structure in c++ for performance?
我希望有一个不同数量的n个对象的类,这些对象很容易作为一个组进行迭代,每个对象成员都有一个影响类方法的单独修改变量的大列表(20+(。 在我开始学习 OOP 之前,我只会创建一个 2D 数组并将变量值加载到对应于每个对象的每行中,然后根据需要追加/删除行。 这仍然是一个好的解决方案吗? 有没有更好的解决方案?
同样,在这种情况下,我更感兴趣的是提高处理器性能,而不是保留抽象和模块化等。 在这方面,我对数据容器最终读入 L1 缓存的方式以及如何确保我不会引起页面效率低下或缓存未命中感到非常困惑。 例如,如果我有一个 128 kb 的缓存,我认为整个容器应该适合这个缓存才能高效,对吗?
根据 Agner Fog 的优化手册,C++ 标准模板库效率相当低,因为它广泛使用了动态内存分配。但是,大于必要大小的固定大小数组(例如,因为在编译时不知道所需的大小(也可能不利于性能,因为较大的大小意味着它不会轻易放入缓存中。在这种情况下,STL 的动态内存分配可以更好地执行。
通常,最好将数据存储在连续内存中。为此,您可以使用固定大小的数组或std::vector
。但是,在使用std::vector
之前,出于性能原因,您应该调用std::vector::reserve()
,以便不必过于频繁地重新分配内存。如果过于频繁地重新分配,堆可能会变得碎片化,这也不利于缓存性能。
理想情况下,您正在处理的数据将完全适合 1 级数据缓存(在现代台式机处理器上约为 32 KB(。但是,即使它不适合,2 级缓存也要大得多(约 512 KB(,而 3 级缓存是几兆字节。更高级别的缓存仍然比从主内存读取要快得多。
最好是内存访问模式是可预测的,以便硬件预取程序可以最好地完成其工作。对于硬件预取程序来说,顺序内存访问最容易预测。
如果多次访问相同的数据,并且数据足够小,可以保存在缓存中,则 CPU 缓存效果最佳。但是,即使数据仅使用一次,CPU 缓存仍可以通过使用预取来加快内存访问速度。
如果出现以下情况,则会发生缓存未命中
- 数据是首次访问,硬件预取程序无法及时预测和预取所需的内存地址,或者 数据
- 不再缓存,因为缓存必须为其他数据腾出空间,因为数据太大而无法放入缓存。
除了硬件预取程序尝试提前预测所需的内存地址(这是自动的(之外,程序员还可以明确发出软件预取。但是,从我所读到的内容来看,除非在非常特殊的情况下,否则很难从这样做中获得显着的性能提升。
- 空基优化子对象的地址
- 关闭||运算符优化
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 返回值优化:显式移动还是隐式
- 人脸跟踪arduino代码的优化
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 纯函数,为什么没有优化
- 为什么大多数 pair 实现默认不使用压缩(空基优化)?
- 如何以优化的方式同时迭代两个间距不相等的数组
- 小字符串优化(调试与发布模式)
- 浮点定向舍入和优化
- Visual Studio 调试优化如何工作?
- 为什么开关的优化方式与 c/c++ 中的链接不同?
- 线性优化目标函数中的绝对值
- GCC 会优化内联访问器吗?
- gcc 如何优化此循环?
- 如何防止 CUDA-GDB 中的<优化输出>值
- 为什么我的程序在 O0 和 O2 的优化级别返回不同的结果
- 这个C++编译器优化(在自身的实例上调用对象自己的构造函数)的名称是什么,它是如何工作的?
- 使用 std::p air 进行返回值优化