重复相同计算的优化
Optimization of repeated identical computations
考虑以下两个函数:
std::pair<double,Vector> myMatrixOperation1(Matrix const& A, Vector const& V) {
Vector AV = A*V;
double norm_A_V = std::sqrt(dot(V,AV));
return make_pair(norm_A_V,AV);
}
std::pair<double,Vector> myMatrixOperation2(Matrix const& A, Vector const& V) {
return make_pair( norm(V,A) , A*V );
}
double norm(Vector const& V, Matrix const& innerProductMatrix) {
double norm_A_V = std::sqrt(dot(V,innerProductMatrix*V));
}
它们显然做同样的事情,除了保证在第一个函数中只计算一次矩阵-向量乘积。
然而,第二个函数更容易读,因为它被重构,以便有一个完全的关注点分离:向量对任意内积的范数的概念被抽象成一个单独的函数。
现在的问题是,没有任何优化,矩阵向量乘积现在计算两次。
我的问题是:编译器是否足够聪明,只计算一次矩阵-向量乘积?如果是,我需要做什么?
我想至少我需要内联norm()函数。此外,关于算子*(矩阵常数&;A、向量常量;V)、懒惰的评价有什么帮助吗?(旁注:我正在使用特征库)
注意:我意识到一个类似的问题:编译器会优化重复的数学计算吗?然而,请注意,我的问题是编译器更难,因为操作符*(矩阵const&A、向量常量;V)不是内置的,因此编译器应该需要一些关于它的保证
编辑:经过进一步的思考,这段引文来自维基百科(http://en.wikipedia.org/wiki/Optimizing_compiler):
例如,在某些语言中,函数不允许有副作用。因此,如果一个程序多次调用同一个函数使用相同的参数,编译器可以立即推断函数的结果只需要计算一次。在语言在允许函数有副作用的地方,另一种策略是可能的。优化器可以确定哪个函数没有边效果,并将此类优化限制为无副作用功能。只有当优化器有访问被调用的函数。
似乎编译器可以用第一个函数替换第二个函数,前提是operator+是纯的(即:没有副作用)。根据https://stackoverflow.com/a/5464114/1583122,在c++中,可以通过告诉编译器一个函数是constexpr,只有constexpr函数调用,并且有const参数来保证它的纯洁性。所以我认为编译器有可能保证这样的优化,只要满足一些要求。此外,请注意,c++ 14
如果在这段代码中优化速度很重要,我根本不会依赖编译器的行为。
即使一个聪明的编译器发现了这个技巧(我在这里表示怀疑,因为这涉及到相当多的语义洞察力——使函数内联可能会提示编译器),你也不能保证另一个编译器会看到它。甚至一个未来版本的相同!
经常出现这样的数值算法依赖于中间结果的重用。如果您清楚地注释为以后保留结果,我认为没有可读性问题。代码紧凑并不总是意味着代码的可读性。
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- 递归函数计算序列中的平方和(并输出过程)
- 空基优化子对象的地址
- 什么是使用 opencv::Mat 优化 c++ 矩阵计算
- 优化递归问题以计算超级数字
- C/C++编译器是否会通过重用最近计算的函数结果来优化代码?
- 优化三角矩阵计算的 CUDA 内核执行
- 从第二个导数计算的曲线的SIMD优化
- 只有当循环中更新的变量是局部变量时,计算才会优化
- 优化标志会导致计算错误
- 优化稀疏矩阵中的对数熵计算
- 用于并行计算的C++代码优化示例
- 行列式计算函数的优化
- 我如何优化高斯pdf的计算
- 重复相同计算的优化
- 优化了数组元素的计算和设置
- 如何优化计算除数
- 为什么优化标志 (-O3) 不能加快四倍精度计算的速度?
- 在高度优化的代码中计算代码运行时
- 计算乘数和除数值的优化算法