大块系数明智的乘法在特征库c++中失败
Large block coefficient-wise multiplication fails in Eigen library C++
我已经阅读了很多文档,但是如果你发现一些我错过的东西,可以解释我的问题,我会很高兴。作为背景,我在Visual Studio 2015中使用3.2.7 Eigen Library在x86 Windows 10上编译。3.2.7版本是从5月开始的,虽然从那以后有过发布,但我在更新日志中没有看到任何表明我的问题已经解决的内容。
这个问题似乎只出现在大于一定大小的矩阵上。我不知道这是系统特有的副产品还是本征固有的东西。
下面的代码在Debug和Release模式下都会产生访问冲突。
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时,这个问题变得有趣,然后访问冲突就不会出现。没错,256 × 254的mx2维度会产生这个问题但是255 × 254的维度不会。如果我增加列的大小,我也会得到访问冲突,所以问题可能与条目的总数有关。即使mx1和mx2填充了值,也会出现问题,没有必要填充矩阵来重现问题。
不将topRows()块赋值给temp的类似代码在Release模式下不会产生访问冲突。我相信还有更多的事情要做,因为我最初在代码中发现了这个问题,这个问题相当复杂,它只出现在一定数量的循环之后(循环之间的矩阵大小是一致的)。我的代码中有太多的内容,以至于我无法隔离访问冲突只在一定数量的循环之后出现的条件。
我想知道的是
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);
看起来像一个影响小维度的bug。删除引起错误的行中的注释以获得正确的结果。
修正。正如迦勒的回答所指出的,这是一种混叠。它是使用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
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- 特征::矩阵<双精度,1,3> 结构类型函数中的返回类型函数
- 有没有一种方法可以通过"typedef"为重新定义的基本类型定义特征和强制转换运算符
- 特征命名访问向量段
- 将特征矩阵的向量设置为0
- 特征:模板函数中矩阵的平面图
- basic_string的前导/尾部不区分空格的特征
- 特征 3 类的模板专用化
- 特征 c++:复矩阵的面积双曲正切(atanh)
- C++ 中的特征向量计算
- 根据C++标准的定义实现"is_similar"类型特征
- C++类型特征,以查看是否可以<uint32_t>对类型"K"的任何变量调用"static_cast(k)"
- 有没有办法找到特征矩阵系数的中值?
- 如何将高维数据映射到特征类型?
- 将平面阵列重塑为复杂的特征类型
- 特征 LLT 模块给出不正确的结果?
- 特征模板化函数和维度
- 特征稀疏向量:求最大系数
- 特征 3.3.x:如何在所有行中操作 lamba?
- 如何将向量断言到特征矩阵