问题已经从术语“表达模板(ET)”开始。我不知道是否有确切的定义。但是在其常见用法中,它以某种方式将“如何编码线性代数表达式”和“如何计算”结合在一起。例如:
您对向量运算进行编码
v = 2*x + 3*y + 4*z; // (1)
它通过循环来计算
for (int i=0; i<n; ++i) // (2)
v(i) = 2*x(i) + 3*y(i) + 4*z(i);
我认为这是两件事,需要分开:(1)是一个接口,(2)一个可能的实现。我的意思是这是编程中的普遍做法。当然(2)可能是一个很好的默认实现,但总的来说,我希望能够利用专门的专用实现。例如,我想要一个像
myGreatVecSum(alpha, x, beta, y, gamma, z, result); // (3)
在编码时被调用(1)。也许(3)仅在内部使用(2)中的循环。但是根据向量大小,其他实现可能会更有效。无论如何,一些高性能专家可以尽可能地实施和调整(3)。因此,如果(1)无法映射到(3)的调用,那么我宁愿避开(1)的语法糖,而直接直接调用(3)。
我所描述的并不是什么新鲜事物。相反,这是BLAS / LPACK背后的想法:
- LAPACK中的所有关键性能操作都是通过调用BLAS函数来完成的。
- BLAS只是为通常需要的线性代数表达式定义一个接口。
- 对于BLAS,存在不同的优化实现。
如果BLAS的范围不足(例如,它没有提供(3)的功能),则可以扩展BLAS的范围。因此,这个60年代和70年代的恐龙通过其石器时代工具实现了界面和实现方式的干净且正交的分离。(大多数)数字C ++库没有达到此级别的软件质量,这很有趣。尽管编程语言本身要复杂得多。因此,毫不奇怪,BLAS / LAPACK仍然活着并得到积极发展。
因此,在我看来,ET本身并不是邪恶的。但是它们如何在数值C ++库中普遍使用,在科学计算界赢得了非常不好的声誉。