首页 > 解决方案 > 将一个块从 Eigen::Matrix 复制到同一矩阵的另一个块时,会出现什么混叠问题?

问题描述

我想使用 Eigen 将矩阵的一部分复制到矩阵本身的另一部分。我想确保了解别名的后果,以便eval()仅在真正需要时使用。

假设我有以下内容:

MatrixXd M(4,4);
M << 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16;
M.block( some indices ) = M.block( some other indices )

我认为应该考虑3种情况:

案例1:块不重叠

这根本不应该是一个问题。一个例子是:

M.topLeftCorner(2,2) = M.bottomRightCorner(2,2);

给我们:图片链接

情况2:块重叠;目标块中的第一个位置在源块的第一个之前

一个例子是:

M.topLeftCorner(2,2) = M.block(1,0,2,2);

在这种情况下,我希望会发生这样的事情:图片链接

我相信这不是混叠的例子。但是,要获得这样的行为,需要保证元素按顺序逐个复制,从左上角开始,在两个块中逐行进行。

案例3:块重叠;目标块中的第一个位置在源块的第一个之后

在这里,我希望出现混叠。一个例子是:

M.block(1,0,2,2) = M.topLeftCorner(2,2);

结果类似于:图片链接

结论

总结一下:

  1. 希望在第一种情况下出现混叠
  2. 鉴于“有序副本”假设,我不会在第二种情况下假设别名
  3. 总是希望在第三种情况下出现别名

这些结论正确吗?“有序副本”的假设是否正确?我想矢量化实际上可以使这个假设无效......

标签: eigen3

解决方案


您对第 1 点是正确的。如果块不重叠,则不会出现混叠问题。

但是,对于 2. 和 3. 您可能有也可能没有别名问题,具体取决于 Eigen 版本、目标体系结构和编译器——本质上这些操作的结果是未定义的。即,您不应该依赖当前的行为。

如果您想有一些明确的行为(不使用临时),您可以手动循环遍历矩阵的非重叠块。代替

M.topLeftCorner(2,2) = M.block(1,0,2,2);

你可以这样写:

for(int c=0; c<2; ++c)
    M.block(0,c,2,1) = M.block(0,c+1,2,1);

或者更好的是,重新考虑您的整体算法,以避免在矩阵内复制重叠块。

有关别名的更多详细信息,请参阅此页面:http ://eigen.tuxfamily.org/dox-devel/group__TopicAliasing.html


推荐阅读