繁体   English   中英

在Eigen库C ++中大块系数逐次乘法失败

[英]Large block coefficient-wise multiplication fails in Eigen library C++

我已经阅读了很多文档 ,但是,如果您发现我想念的东西可以解释我的问题,我会很高兴的。 对于背景,我正在使用3.2.7本征库在Visual Studio 2015中的x86 Windows 10上进行编译。 3.2.7版本是从5月开始的,此后一直有版本发布,但我在变更日志中没有看到任何表明我的问题已解决的信息。

该问题似乎仅出现在一定大小以上的矩阵上。 我不知道这是我系统特有的东西还是Eigen固有的东西的副产品。

以下代码在“调试”和“发布”模式下都会产生访问冲突。

int mx1Rows = 255, cols = 254;
{//this has an access violation at the assignment of mx2
        Eigen::MatrixXd mx1(mx1Rows, cols);
        Eigen::MatrixXd mx2(mx1Rows + 1, cols);
        Eigen::Block<Eigen::MatrixXd, -1, -1, false> temp = mx2.topRows(mx1Rows);
        mx2 = temp.array() * mx1.array();//error
}

我认为按系数乘法的分配是安全的,因为结果应为别名

当mx1Rows减少为值254,然后不会出现访问冲突时,此问题变得很有趣。 没错,mx2尺寸为256 x 254会产生问题,但尺寸255 x 254不会。 如果增加列大小,我也会遇到访问冲突,因此问题可能与条目总数有关。 即使mx1和mx2都填充了值,也会出现问题,但无需填充矩阵即可重现问题。

没有将topRows()块分配给temp的类似代码在“释放”模式下不会产生访问冲突。 我相信还有更多的东西,因为我最初在代码中发现这个问题要复杂得多,并且仅在一定数量的循环后才会出现(矩阵大小在各个循环之间是一致的)。 我的代码中发生了太多事情,以至于我无法隔离导致访问冲突仅在一定数量的循环之后才会出现的情况。

我很好奇的是

1)我是否以某种明显错误的方式使用Eigen?

2)您能够重现此问题吗? (您的环境详细信息是什么?)

3)这是特征库中的错误吗?

通过将块分配给一个临时矩阵而不是一个块来解决此问题很容易,即使它效率不高,因此我对此一无所知。

问题在于temp引用了mx2所持有的系数,但是在最后一次赋值中,首先对mx2进行大小调整,然后对表达式进行求值。 因此,在表达式的实际求值过程中, temp引用了垃圾。 更准确地说,这是实际生成的内容(以简化的方式):

double* temp_data = mx2.data;
free(mx2.data);
mx2.data = malloc(sizeof(double)*mx1Rows*cols);
for(j=0;j<cols;++j)
  for(i=0;i<mx1Rows;++i)
    mx2(i,j) = temp_data[i+j*(mw1Rows+1)] * mx1(i,j);

这称为别名问题

您可以通过临时评估表达式来解决:

mx2 = (temp.array() * mx1.array()).eval();

另一个解决方案是将mx2.topRows(.)复制到拥有自己内存的真正MatrixXd

MatrixXd temp = mx2.topRows(mx1Rows);
mx2 = temp.array() * mx1.array();

另一个解决方案是评估temp并随后调整大小:

Block<MatrixXd, -1, -1, false> temp = mx2.topRows(mx1Rows);
temp = temp.array() * mx1.array();
mx2.conservativeResize(mx1Rows,cols);

看起来也像一个影响小尺寸的错误。 删除导致错误的代码行中的注释以获得正确的结果。

更正。 正如ggael的答案所指出的,这是混叠。 这种类型经常使用auto创建一个临时使用的温度,然后在同一对象上使用。

#include <iostream>
#include <Eigen/Dense>

int main()
{//this has an access violation at the assignment of mx2
    //const int mx1Rows = 255, cols = 254;
    const int mx1Rows = 3, cols = 2;
    Eigen::MatrixXd mx1(mx1Rows, cols);
    int value = 0;
    for (int j = 0; j < cols; j++)
        for (int i = 0; i < mx1Rows; i++)
            mx1(i,j)=value++;
    Eigen::MatrixXd mx2(mx1Rows + 1, cols);
    for (int j = 0; j < cols; j++)
        for (int i = 0; i < mx1Rows+1; i++)
            mx2(i,j)=value++;
    Eigen::Block<Eigen::MatrixXd, -1, -1> temp = mx2.topRows(mx1Rows);
    mx2 = temp.array()/*.eval().array()*/ * mx1.array();r
    std::cout << mx2.array() << std::endl;
}

// with /*.eval().array()*/ uncommented
//0 30
//7 44
//16 60

// Original showing bug
//-0 -4.37045e+144
//-1.45682e+144 -5.82726e+144
//-2.91363e+144 -7.28408e+144

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM