MatrixXf mat1(2,2);
mat1 << 1, 2, 4, 7;
MatrixXf mat2 = mat1;
auto result = mat1 * mat2;
Run Code Online (Sandbox Code Playgroud)
Eigen mat1 * mat2在临时矩阵中评估乘积,然后result在计算后将其用于初始化。如result右图所示,我们不需要别名:
MatrixXf result;
result.noalias() = mat1 * mat2;
Run Code Online (Sandbox Code Playgroud)
现在,将产品mat1 * mat2直接评估为result。
到目前为止,一切都很好。但是在这种情况下会发生什么呢?
template <typename T1, typename T2>
auto multiplication(const T1& A, const T2& B) // I'm using C++17, decltype not needed
{
return A*B;
}
int main()
{
auto result = multiplication(mat1, mat2); // say mat1 and mat2 are the same as above
// or even this
mat1 = multiplication(mat1, mat2);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我要说的multiplication(m1,m2)是rvalue,result由于RVO 直接构建了别名,因此不会出现别名。我想对这行表示相同的意思。mat1 = multiplication(mat1, mat2).然后我们可以说,有一种方法可以mat1与另一个矩阵相乘,并将结果存储在同一矩阵中,mat1而无需使用临时矩阵(因此,避免了混叠)。
问题:
Eigen是在这里假设锯齿还是我的假设正确?
您还应该阅读有关使用关键字的常见陷阱auto。
如果你写
MatrixXf mat1, mat2;
auto result = mat1 * mat2;
Run Code Online (Sandbox Code Playgroud)
要么
template <typename T1, typename T2>
auto multiplication(const T1& A, const T2& B) { return A*B; }
Run Code Online (Sandbox Code Playgroud)
则auto实际的类型仅类似于Product<MatrixXf, MatrixXf>或Product<T1,T2>,也就是说,此时完全不进行任何计算。
因此
MatrixXf mat1 = MatrixXf::Random(2,2), mat2 = MatrixXf::Random(2,2);
auto result = multiplication(mat1, mat2); // no computation happens here
// this is safe (Eigen assumes aliasing can happen):
mat1 = result; // equivalent to directly assign mat1 = mat1 * mat2;
// Pitfall: "result" no refers to a modified `mat1` object!
// this will give undefined results (you may need bigger matrices to actually see this):
mat1.noalias() = mat1*mat2; // tell Eigen this does not alias, but actually it does.
Run Code Online (Sandbox Code Playgroud)
附录:在注释中指出了赋值和初始化之间的区别。实际上,在初始化过程中,Eigen假定不会发生任何混叠现象,例如,以下结果直接分配给结果(无临时变量):
MatrixXf result = mat1 * mat2; // initialization, not assignment!
Run Code Online (Sandbox Code Playgroud)
附录2:如果您写过(假设返回类型foo为Object):
Object A;
A = foo(A);
Run Code Online (Sandbox Code Playgroud)
必须发生某种隐式赋值(C ++ 11可能会进行移动赋值,如果Object允许的话)。这与
Object A;
Object B = foo(A); // RVO possible (depending on foo).
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
99 次 |
| 最近记录: |