我正在阅读这篇文章,这家伙继续谈论如何让每个人都受益匪浅从数据导向设计与OOP混合。但是,他没有显示任何代码示例。

我搜索了这个,但是找不到任何关于这是什么的真实信息,更不用说任何代码示例了。有人熟悉这个术语并且可以提供一个例子吗?对于别的东西,这可能是另一个词吗?

有帮助吗?

解决方案

首先,不要将此与数据驱动设计混淆。

我对面向数据的设计的理解是,它是关于组织数据以进行有效处理。特别是关于缓存未命中等。另一方面,数据驱动设计是关于让数据控制你的许多程序行为(由 Andrew Keith的回答)。

假设您的应用程序中有球对象,其颜色,半径,弹性,位置等属性。

面向对象的方法

在OOP中你会像这样描述你的球:

class Ball {
  Point  position;
  Color  color;
  double radius;

  void draw();
};

然后你会创建一个这样的球集合:

vector<Ball> balls;

面向数据的方法

在面向数据的设计中,您更有可能编写如下代码:

class Balls {
  vector<Point>  position;
  vector<Color>  color;
  vector<double> radius;

  void draw();
};

正如你所看到的,没有一个单位代表一个球了。球对象仅隐含存在。

这可以在性能方面具有许多优点。通常我们希望同时对许多球进行操作。硬件通常需要大量连续的内存块才能高效运行。

其次,您可能会执行仅影响部分球属性的操作。例如。如果您以各种方式组合所有球的颜色,那么您希望缓存仅包含颜色信息。但是,当所有球属性存储在一个单位中时,您也将拉入球的所有其他属性。即使你不需要它们。

缓存使用示例

说一个球,每个球占用64个字节,一个点占用4个字节。缓存槽也需要64个字节。如果我想更新10个球的位置,我必须将10 * 64 = 640字节的内存拉入缓存并获得10个缓存未命中。但是,如果我可以将球的位置作为单独的单位工作,那将只需要4 * 10 = 40个字节。这适合一次缓存提取。因此,我们只获得1次缓存未命中以更新所有10个球。这些数字是任意的我假设缓存块更大。

但它说明了内存布局如何具有严重影响缓存命中率和性能。随着CPU和RAM速度之间的差异变宽,这只会增加重要性。

如何布局内存

在我的球示例中,我对问题进行了大量简化,因为通常对于任何普通应用,您可能会同时访问多个变量。例如。位置和半径可能会经常一起使用。然后你的结构应该是:

class Body {
  Point  position;
  double radius;
};

class Balls {
  vector<Body>  bodies;
  vector<Color>  color;

  void draw();
};

您应该这样做的原因是,如果一起使用的数据放在不同的数组中,则存在竞争缓存中相同插槽的风险。因此加载一个会抛弃另一个。

因此,与面向对象编程相比,您最终创建的类与问题的心理模型中的实体无关。由于数据是根据数据使用情况汇总在一起的,因此您不会总是有合理的名称来为数据导向设计提供类。

与关系数据库的关系

数据导向设计背后的思想与您对关系数据库的看法非常相似。优化关系数据库还可以涉及更高效地使用缓存,尽管在这种情况下,缓存不是CPU缓存放置在内存中的页面。一个好的数据库设计人员也可能会将不经常访问的数据拆分成一个单独的表,而不是创建一个包含大量列的表,而这些列只有少数列使用过。他也可能选择对某些表进行非规范化,以便不必从磁盘上的多个位置访问数据。就像数据导向设计一样,这些选择是通过查看数据访问模式是什么以及在何处进行的

其他提示

Mike Acton最近公开谈论了面向数据的设计

我对它的基本总结是:如果你想要性能,那么考虑一下数据流,找到最有可能与你混淆的存储层并优化它很难。迈克正在关注关于L2缓存未命中,因为他正在实时,但我想同样的事情适用于数据库(磁盘读取)甚至Web(HTTP请求)。我认为这是进行系统编程的一种有用方式。

请注意,它并不能免除您对算法和时间复杂性的影响,它只会将您的注意力集中在找出您必须以疯狂的CS技能为目标的最昂贵的操作类型。

我只是想指出Noel正在具体谈论我们在游戏开发中面临的一些具体需求。我认为其他正在进行实时软模拟的部门将从中受益,但它不太可能成为一种能够显着改善一般业务应用的技术。此设置用于确保从底层硬件中挤出最后一点性能。

面向数据的设计是一种设计,其中应用程序的逻辑由数据集构成,而不是程序算法。例如

程序方法。

int animation; // this value is the animation index

if(animation == 0)
   PerformMoveForward();
else if(animation == 1)
  PerformMoveBack();
.... // etc

数据设计方法

typedef struct
{
   int Index;
   void (*Perform)();
}AnimationIndice;

// build my animation dictionary
AnimationIndice AnimationIndices[] = 
  {
      { 0,PerformMoveForward }
      { 1,PerformMoveBack }
  }

// when its time to run, i use my dictionary to find my logic
int animation; // this value is the animation index
AnimationIndices[animation].Perform();

这样的数据设计促进了数据的使用,以构建应用程序的逻辑。它更容易管理,特别是在视频游戏中,可能有数千条基于动画或其他因素的逻辑路径。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top