如何在c++中实现与抽象类指针向量的缓存一致性
How to achieve cache coherency with an abstract class pointer vector in C++?
我正在用c++做一个小游戏。我在StackExchange网站上找到了关于缓存一致性的答案,我想在我的游戏中使用它,但我使用抽象类实体的子类。
我将所有实体存储在std::vector中,这样我就可以在循环中访问虚函数。Entity::update()是Entity的虚函数,它被子类覆盖,比如PlayerEntity。
在Game.hpp - Private Member Variables:
std::vector<Entity*> mEntities;
PlayerEntity* mPlayer;
在Game.cpp - Constructor:
mPlayer = new PlayerEntity();
mEntities.push_back(mPlayer);
我的update函数(在主循环中)是这样的:
void Game::update() {
for (Entity* entity : mEntities) {
entity->update(mTimeStep, mGeneralClock.getElapsedTime().asMilliseconds());
}
}
我的问题是:我如何使我的实体对象在内存中彼此相邻,从而实现缓存一致性?我试图简单地使指针的向量成为对象的向量,并进行适当的更改,但是由于显而易见的原因,我不能使用多态性。侧面问题:什么决定了一个对象在内存中分配的位置?我整件事都做错了吗?如果是这样,我应该如何存储我的实体?
注意:如果我的英语不好,我很抱歉,我的母语不是英语。
显然,首先衡量哪些部分甚至值得优化。并非所有游戏都是一样的,游戏中的代码也不是一样的。完全重组触发最终boss死亡动画的脚本,使其使用1条缓存线而不是2条是没有意义的。也就是说…
如果你的目标是优化缓存,忘记继承和虚函数。或者至少批评他们。正如你所注意到的,创建一个连续的多态对象数组是很难的。容易出错且完全不可行的(取决于子类是否有不同的大小)。
您可以尝试创建一个池,使附近的实体(在实体向量中)更有可能彼此靠近(在内存中),但坦率地说,我怀疑您会比最先进的通用分配器做得更好,特别是当实体的大小和生命周期变化很大时。只有当向量中相邻的实体被连续分配时,池才有帮助。但是在这种情况下,任何标准分配器都具有相同的局部性优势。它不像tcmalloc
和朋友们随机选择一个缓存线来分配只是为了惹恼你。
您可能能够从了解对象类型中挤出一点内存,但这纯粹是假设的,必须首先证明实现它的努力是合理的。还要注意,运行磨矿池要么假设所有对象大小相同,要么永远不会释放单个对象。同时允许这两种情况会使您朝着通用分配器迈进一半,而您肯定会做得更差。
您可以根据对象的类型隔离对象。也就是说,不再只有一个具有虚函数的多态Entity
的向量,而是有N个向量:vector<Bullet>
、vector<Monster>
、vector<Loot>
等。这并没有听起来那么疯狂,原因有三:
- 通常,您可以将管理这样一个矢量的整个业务拉到专用系统中。所以最后你甚至可能有一个
vector<System *>
,其中每个System
都有一个向量用于一种东西,并在一个虚拟调用中更新所有这些东西(委托给许多静态分配的调用)。 - 您不需要在此抽象中表示中的所有。不是每个小整数都需要用自己的实体类型包装。
- 如果您沿着这条路线走下去,并从实体组件系统中获得提示,您还可以获得用于代码重用的继承的另一种选择(
class Monster : Entity {}; class Skeleton : Monster {};
),它具有来之不易的缓存友好性。
这并不容易,因为多态性不能很好地与缓存一致性一起工作。
我认为最好是重载基类的new操作符来从池中分配内存。但是要做到这一点,您需要知道所有派生类的大小,并且在进行一些分配/释放之后,您可以使用内存碎片,这将降低增益。
看看Cachegrind,它是一个模拟程序如何与机器的缓存层次结构交互的工具。
- 函数向量_指针有不同的原型,我可以构建一个吗
- 有没有一种"cleaner"的方法可以在指向基的指针向量中找到派生类的第一个实例?
- 使用向量类的c++指针
- 如何使用C++初始化向量;脚本化值不是数组、指针或矢量错误
- 如何更改唯一指针向量的可见性
- C++ 独特指针练习的向量
- C 中的向量指针的清晰图
- 当向量位于内部类中时,如何删除指向对象的向量指针
- std::向量指针
- 指向结构体的向量指针错误
- 删除指向指针的向量指针时出错
- 映射不同类型的向量指针
- 在c++中传递向量指针
- 虚拟类的向量:指针是干净的方法吗
- 如何从另一个向量/对象集构造新的向量/指针集
- 模型视图控制器- c++向量指针,太多的传递
- 为什么向量指针占用这么多内存?
- 删除条目向量指针的静态映射c++
- 复向量指针
- c++数组向量指针的初始化