我可以想象表达式模板会为诸如向量/矩阵/四元数等普遍存在的事物编译时间做可怕的事情,但是如果它的速度提升如此之大,为什么游戏不使用它呢?很明显,SIMD 指令可以很好地利用数据级并行性。表达式模板和惰性求值结合起来似乎很有意义,至少在消除临时变量方面是这样。
因此,虽然像 Eigen 这样的库宣传这些功能,但我认为这在中间件(例如 Havok)或对速度至关重要的游戏中并不常见。任何人都可以对此有所了解吗?它与非确定性或分支预测有关吗?
我可以想象表达式模板会为诸如向量/矩阵/四元数等普遍存在的事物编译时间做可怕的事情,但是如果它的速度提升如此之大,为什么游戏不使用它呢?很明显,SIMD 指令可以很好地利用数据级并行性。表达式模板和惰性求值结合起来似乎很有意义,至少在消除临时变量方面是这样。
因此,虽然像 Eigen 这样的库宣传这些功能,但我认为这在中间件(例如 Havok)或对速度至关重要的游戏中并不常见。任何人都可以对此有所了解吗?它与非确定性或分支预测有关吗?
我能想到很多原因:
当然,还有一个显而易见的问题:他们会在哪里使用表达式模板?是否有足够复杂的数学来真正让它变得有价值?游戏往往依赖于相当少量的线性代数运算,在任何情况下通常都需要大量手动调整。
我想再补充一个上述答案中未说明的原因。抱歉,如果是的话,我错过了。
将模板添加到基于数学的类(例如 vec3 类)会改变运算符的含义并导致函数对某些模板类型无效。
举个例子,
vec3<int> myVec( 3, 5, 4 );
myVec.Normalize();
归一化对整数向量意味着什么?突然间,当我们将模板添加到数学结构时,我们会使许多现有函数失效,例如上面描述的示例。
另外,值得一提的是,许多数学结构都针对某些类型进行了优化,因为优化在游戏中非常重要。GPU 是浮点计算机。双精度数占用浮点数的两倍空间,并且计算起来相当慢,尽管对于新游戏开发人员来说这似乎是一个明显的用例。
我希望这个例子有意义。模板是一个很好的工具,但游戏中的数学结构并不是使用它们的正确地方。
通常,游戏中对性能敏感且数学繁重且仍倾向于在 CPU 而不是 GPU 上运行的部分将相同的基本操作应用于大量元素。一些例子是动画混合、物理计算、可见性测试等。
在当前控制台硬件上优化此类问题的最佳方法通常是尝试和批处理尽可能多的工作,并以最大的数据局部性为目标,以避免代价高昂的缓存未命中。然后可以使用 SIMD 内在函数优化实际数学,并且通常会仔细手动优化。表达式模板为您提供的优化可以在手动优化阶段相对容易地执行,但也有可能执行表达式模板不会给您的各种其他重要优化。通常,这些关键代码将包含针对每个目标平台进行自定义优化的部分,并且移植性不强。
我认为表达式模板没有被广泛使用的原因是它们增加了软件复杂性(由于 jalf 描述的所有原因)到非性能关键代码中,这些代码并没有真正保证它,同时没有涵盖所有必要的优化显示在配置文件顶部的真正性能关键代码。