微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决面向数据的设计和缓存局部性

在 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 举报,一经查实,本站将立刻删除。