面向数据的设计和缓存局部性

问题描述

在 Richard Fabian 的面向数据的设计中,他给出了一个基于组件的游戏对象示例,其中一个对象可以具有的不同属性被分离到不同的数组中,并且功能是通过处理这些数组中的数据。他举了一个渲染的例子:

struct Orientation { vec pos,up,forward,right; };
SparseArray<Orientation> orientationArray;
SparseArray<Vec> velocityArray;
SparseArray<bool> isVisible;
SparseArray<AssetID> modelArray;

void RenderUpdate() {
    foreach( {index,assetID} in modelArray) {
        if( index in isVisible ) {
            gRenderer.AddModel( assetID,orientationArray[ index ] );
        }
    }
}

让我感到困惑的是这段代码如何对缓存友好。据我了解,面向数据的设计通过将特定操作所需的相关数据保存在连续内存中来实现更好的性能,因此当您遍历数据进行更新时,您将减少缓存未命中的次数。然而,在这个例子中,渲染需要来自 3 个不同“组件”的信息,因此在每次迭代中,您将访问不同的数据数组,更不用说潜在的 如果任何组件需要与彼此的数据交互,则必须查找 ID 会降低性能。

我正在开发一个非常简单的 2D 游戏来练习面向数据的设计。如果我要在我的游戏中模拟一个基本行为,比如让物体按照上面给出的模式移动,它会是这样的:

struct Position { int x,y; };
struct Velocity { int x,y; };
SparseArray<Position> positionsArray;
SparseArray<Velocity> velocitiesArray;

然后在物理更新中,我会将 Position 中的每个 positionsArray 更新为 Velocity 中对应的 velocitiesArray

缓存将这个操作所需的数据组合成一个单一的结构不是更好吗:

struct MoveComponent { Position pos; Velocity vel };
SparseArray<MoveComponent> moveComponents;

所以您拥有更新所有连续存储的位置所需的数据?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...