本征是否假设混叠?
Does Eigen assume aliasing?
矩阵乘法是特征中唯一默认采用混叠的操作。
MatrixXf mat1(2,2);
mat1 << 1, 2, 4, 7;
MatrixXf mat2 = mat1;
auto result = mat1 * mat2;
Eigen 在临时矩阵中评估乘积mat1 * mat2
,然后在计算后用于初始化result
。由于result
没有出现在右侧,因此我们不需要混叠:
MatrixXf result;
result.noalias() = mat1 * mat2;
现在,产品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;
}
我会说没有发生混叠,因为multiplication(m1,m2)
是一个rvalue
,并且由于 RVO 直接在result
中构建。我会对行说同样的话mat1 = multiplication(mat1, mat2).
然后我们可以说有一种方法可以将mat1
与另一个矩阵相乘,并将结果存储在相同的矩阵mat1
中,而无需使用临时矩阵(因此,避免混叠(。
问题:
本征在这里假设混叠还是我的假设是正确的?
您还应该阅读有关使用auto
关键字的常见陷阱。
如果你写
MatrixXf mat1, mat2;
auto result = mat1 * mat2;
或
template <typename T1, typename T2>
auto multiplication(const T1& A, const T2& B) { return A*B; }
那么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" now 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.
附录:在评论中指出了赋值和初始化之间的区别。事实上,在初始化过程中,Eigen 假设没有发生混叠,例如,以下直接分配给结果(没有临时(:
MatrixXf result = mat1 * mat2; // initialization, not assignment!
附录 2:如果您编写(假设foo
的返回类型为Object
(:
Object A;
A = foo(A);
必须发生某种隐式赋值(如果Object
允许的话,C++11 可能是移动赋值(。这与
Object A;
Object B = foo(A); // RVO possible (depending on foo).
相关文章:
- 在提升multi_index容器中,是否定义了"default index"?
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 假设相同的 lambda 表达式具有不同的类型是否安全?
- 本征是否假设混叠?
- 假设 C++11 中已知子级布局,重新插入基类是否安全
- 假设浮点数或双 NaN 将始终作为字符串"nan"是否安全?
- 是否不允许编译器假设 const-ref 参数将保持 const?
- 假设钻石继承打破了C++的封装是否正确?
- 假设sqlite3_exec数据库指针不更改其值是否为保存
- 是否可以安全地假设64位指针中的16个高位(2个对我来说足够了)是未设置的
- 我是否应该假设对象的析构函数在从 STL 容器中删除后立即调用?
- 假设所有Windows平台都在UCS-2 LE中是否安全
- 对象数组作为链表中的字符数组 - 我对对齐的假设是否有效
- 假设文件将被打开,我是否相当安全
- &= 是否保证表现得像假设的 &&= 运算符?
- 假设 .. 的值是否总是安全的。流::int_type 是 >= 0 除了 eof
- 我们是否可以假设下列任意一对浮点算术语句总是产生相同的结果?
- 使用concurrent_vector迭代器的算术:假设从迭代器中减去'begin ()'会给出索引是否安全?
- 按值分配成员对象:我的假设是否正确
- 结构件对齐 - 是否可以假设没有填充