为什么游戏不使用表达模板进行数学运算?

时间:2012-02-26 01:59:07

标签: c++ templates optimization expression-templates

我可以想象表达式模板对于像向量/矩阵/四元数等普遍存在的事物的编译时间来说是糟糕的事情,但是如果它是如此大的速度提升为什么游戏不使用呢?很明显,SIMD指令可以利用数据级并行性来产生很好的效果。表达模板和懒惰的评估似乎是有意义的,至少在消除临时性时是这样。

因此,虽然像Eigen这样的图书馆宣传了这些功能,但我并不认为这在中间件(例如Havok)或速度非常快的游戏中常见。任何人都可以对此有所了解吗?它与非确定性或分支预测有关吗?

3 个答案:

答案 0 :(得分:5)

我可以想到很多原因:

  • 它会伤害编译时间。更长的编译时间意味着测试您对代码所做的任何更改都需要更长的时间。它会伤害生产力。
  • 这很复杂。最有可能的是,团队中的许多开发人员不熟悉表达式模板,并且很难阅读和调试它们。
  • 游戏经常需要在多个平台上工作,各种编译器可能存在各种各样的缺点,例如可能会使高级模板技巧成为问题。
  • 通常没有必要。您可以编写没有表达式模板的高效代码。它只是变得更加冗长,你必须为编译器做更多的手工操作。
  • 游戏开发者对10年前尚未在游戏中使用的任何内容持怀疑态度。不久前,几位主要开发人员坚持C:不是因为C ++不够好,而是因为它是“新的”。游戏开发者很保守。

当然,显而易见的问题是:哪里他们会使用表达模板?是否有足够的复杂的数学来真正让它变得有价值?游戏往往依赖于相当少量的线性代数运算,在任何情况下都会经常进行大量的手动调整。

答案 1 :(得分:1)

我想补充一个以上答案中未提及的原因。抱歉,我错过了。

在基于数学的类(例如vec3类)中添加模板可能会改变运算符的含义,并导致某些模板类型的函数无效。

例如

vec3<int> myVec( 3, 5, 4 );
myVec.Normalize();

归一化对整数矢量意味着什么?当我们将模板添加到数学构造中时,突然间,我们使许多现有功能失效,例如上述示例。

另外,还有一件值得一提的事情是,许多数学结构都对某些类型进行了优化,因为优化在游戏中非常重要。 GPU是浮点计算机。尽管双打看起来很明显是一个新游戏开发人员的用例,但双打占用的浮动空间却是其两倍,并且计算起来要慢得多。

我希望这个例子有意义。模板是一个很好的工具,但是游戏中的数学构造并不是使用它们的合适位置。

答案 2 :(得分:0)

通常,游戏中既具有性能敏感性又重数学并且仍然倾向于在CPU而不是GPU上运行的部分正在对大量元素应用相同的基本操作。一些例子是动画混合,物理计算,可见性测试等。

在当前控制台硬件上优化这些问题的最佳方法通常是尝试尽可能多地协同工作,并以最大数据局部性为目标,以避免昂贵的缓存未命中。然后可以使用SIMD内在函数优化实际数学,并且通常会仔细手动优化。表达式模板为您提供的优化类型可以在手动优化阶段相对容易地执行,但是还有各种其他重要的优化也可能是表达式模板无法提供的。通常,这个关键代码将包含针对每个目标平台的自定义优化的部分,并且不会非常便携。

我认为表达式模板没有被广泛使用的原因是它们将软件复杂性(由于jalf描述的所有原因)添加到非性能关键代码中,而这些代码并不真正保证,而没有涵盖所有优化对于显示在配置文件顶部的真正性能关键代码所必需的。