C++ 指针 vector 如何影响性能?

标签 c++ performance pointers vector stl

我想知道指向对象的指针的 std::vector 与使用直接包含对象的 std::vector 相比如何影响程序的性能。具体来说,我指的是程序的速度。

我被教导使用 std::vector 而不是 std::list 等其他 STL,因为它的速度更快,因为它的所有数据都连续存储在内存中,而不是碎片化。这意味着迭代元素很快,但我的想法是,如果我的 vector 包含指向对象的指针,那么对象仍然可以存储在内存中的任何位置,并且只有指针是连续存储的。我想知道在遍历 vector 和访问对象时这将如何影响程序的性能。

我当前的项目设计使用指针 vector ,这样我就可以利用虚函数,但是我不确定这是否值得当我的 vector 变得非常大时我可能遇到的速度下降。感谢您的帮助!

最佳答案

如果你需要多态性,正如人们所说,你应该存储指向基的指针。如果稍后您决定此代码很热并且需要优化它的 cpu 缓存使用,您可以通过使对象完全适合缓存 channel 和/或使用自定义分配器来确保取消引用数据的代码局部性来做到这一点。

Slicing 是当你按值 Base 存储对象并复制构造或分配给它们一个 Derived,Derived 将被切片,复制构造函数或分配器只接受一个 Base 并且将忽略 Derived 中的任何数据,没有足够的空间在 Base 中分配以占用 Derived 的全部大小。即,如果 Base 是 8 个字节,而 Derived 是 16 个字节,那么即使您提供了一个明确采用 Dervived 的复制构造函数/分配器,目标值中也只有足够的空间容纳 Base 的 8 个字节。

我应该说,如果您大量使用不会被优化器忽略的虚拟化,那么考虑数据缓存一致性真的不值得。指令缓存未命中比数据缓存未命中更具破坏性,虚拟化会导致指令缓存未命中,因为它必须在将函数加载到指令缓存之前查找 vtable 指针,因此不能抢先加载它们。

CPU 倾向于将尽可能多的数据预加载到缓存中,如果您加载一个地址,整个缓存 channel (~64 字节)将被加载到缓存 channel 中,并且通常它还会在之前和之前加载缓存 channel 这就是人们如此热衷于数据局部性的原因。

因此,在您的指针 vector 场景中,当您加载第一个指针时,您将立即在缓存中获得大量指针,通过指针加载将触发缓存未命中并加载该对象周围的数据,如果您的实际粒子是 16 个字节并且彼此本地,除此之外你不会丢失太多。如果它们遍布整个堆并且很大,您将在每次迭代中得到非常频繁的缓存搅动,并且在处理粒子时相对正常。

传统上,粒子系统往往非常热并且喜欢将数据紧密打包,通常会看到 16 字节的普通旧数据粒子系统,您可以使用非常可预测的分支对其进行线性迭代。这意味着您通常可以依赖每个缓存 channel 4 个粒子,并让预取器保持在您的代码之前。

我还应该说 cpu 缓存是 cpu 依赖的,我关注的是 intel x86。例如,Arm 往往落后于英特尔,并且管道不那么复杂,预取器的能力较弱,因此缓存未命中的破坏性较小。

关于C++ 指针 vector 如何影响性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43507351/

相关文章:

c# - 连接到 Always On 可用性组的只读实例

性能计数器与 ETW

c - 在c中为结构指针数组声明内存

c++ - 强制转换为 void* 以将对象传递给 C++ 中的 pthread

c++ - 在当前类的构造函数中调用其他类定义的虚函数

c++ - 如何从进程中分离exe

performance - 为什么XOR比OR快得多?

创建一个简单的二叉搜索树

c++ - 使用 Windows GDI 绘制一个点

c++ - SDL2_image 未初始化