我正在读这篇文章,这个家伙继续谈论如何将面向数据的设计与面向对象的设计结合起来,每个人都能从中受益。但是,他没有展示任何代码示例。

我在谷歌上搜索了一下,找不到任何关于这是什么的真实信息,更不用说任何代码示例了。有谁熟悉这个术语并能提供一个例子吗?这个词是不是有别的意思?


当前回答

如果想要利用现代处理器架构,就需要以某种方式在内存中布局数据。cpu非常擅长处理在内存中按顺序排列的简单类型。任何其他布局的处理成本都高得多。

在面向对象的方法中,您总是考虑一个实例,然后通过将对象分组到集合中将其扩展到多个实例。但从硬件的角度来看,这带来了额外的成本。

在面向数据的方法中,你不像在面向对象编程中那样有一个“实例”。您的实例可以有一个标识符,类似于关系数据库中的数据,但除此之外,与您的实例相关的数据可以分割到几个表中(表被实现为向量),以实现高效的处理。

举个例子:假设你有一个类Student {int id;std:: string名称;平均浮动;bool毕业;}。在面向对象编程中,你可以把所有的学生放在一个向量中。

在面向数据的设计中,首先要问自己希望对这些数据进行什么样的处理。假设你想计算所有尚未毕业的学生的平均分数。因此,您将创建一个表,其中只包含已毕业的学生和未毕业的学生。您不会在该表中保留学生名,因为它不用于处理。但是你会保留一个学号和一个平均分。

现在计算非毕业学生的平均分意味着遍历非毕业表并执行计算。由于平均标记在内存中是相邻的,您的CPU将使用SIMD并以最有效的方式处理数据。由于我们没有查询已毕业的bool值来测试学生是否已经毕业,因此不会出现数据缓存丢失的情况。

这在理论上听起来不错,但我从未在现实项目中进行过这种开发。如果任何人有任何经验,请联系我,我有很多问题。

其他回答

如果想要利用现代处理器架构,就需要以某种方式在内存中布局数据。cpu非常擅长处理在内存中按顺序排列的简单类型。任何其他布局的处理成本都高得多。

在面向对象的方法中,您总是考虑一个实例,然后通过将对象分组到集合中将其扩展到多个实例。但从硬件的角度来看,这带来了额外的成本。

在面向数据的方法中,你不像在面向对象编程中那样有一个“实例”。您的实例可以有一个标识符,类似于关系数据库中的数据,但除此之外,与您的实例相关的数据可以分割到几个表中(表被实现为向量),以实现高效的处理。

举个例子:假设你有一个类Student {int id;std:: string名称;平均浮动;bool毕业;}。在面向对象编程中,你可以把所有的学生放在一个向量中。

在面向数据的设计中,首先要问自己希望对这些数据进行什么样的处理。假设你想计算所有尚未毕业的学生的平均分数。因此,您将创建一个表,其中只包含已毕业的学生和未毕业的学生。您不会在该表中保留学生名,因为它不用于处理。但是你会保留一个学号和一个平均分。

现在计算非毕业学生的平均分意味着遍历非毕业表并执行计算。由于平均标记在内存中是相邻的,您的CPU将使用SIMD并以最有效的方式处理数据。由于我们没有查询已毕业的bool值来测试学生是否已经毕业,因此不会出现数据缓存丢失的情况。

这在理论上听起来不错,但我从未在现实项目中进行过这种开发。如果任何人有任何经验,请联系我,我有很多问题。

我第一次听说面向数据的设计是在我们的机械播客“S3: EP4面向数据的设计”那一集。https://www.owltail.com/podcast/Atvr2-Our-Machinery

也许这种情况已经改变了,但在一段时间以前,找到关于面向数据设计的信息是很困难的。我找到的唯一一本书是:https://www.manning.com/books/data-oriented-programming

Mike Acton最近做了一个关于面向数据设计的公开演讲:

我对它的基本总结是:如果你想要性能,那么就考虑数据流,找到最有可能破坏你的存储层,然后努力优化它。Mike专注于L2缓存丢失,因为他做的是实时的,但我想同样的事情也适用于数据库(磁盘读取)甚至Web (HTTP请求)。我认为这是一种很有用的系统编程方法。

请注意,它并没有免除您对算法和时间复杂性的思考,它只是将您的注意力集中在找出最昂贵的操作类型上,然后您必须以您疯狂的CS技能为目标。

在面向数据的设计中,应用程序的逻辑是由数据集而不是过程算法构建的。例如

程序的方法。

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();

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

我只是想指出Noel特别谈到了我们在游戏开发中所面临的一些特定需求。我认为其他正在进行实时软模拟的部门将从中受益,但它不太可能是一种对一般业务应用程序有显著改进的技术。这种设置是为了确保从底层硬件中挤出最后一点性能。