我正在使用EIGEN进行稀疏矩阵优化和函数。一切都“正常”,除非在某些情况下,我无法理解这种情况。
事情就是这样:
Matrix A
2 0 0
0 2 0
0 0 2
Matrix B
6 3
0 1
2 8
Result
12 6
0 2
4 16
正如您所看到的,这是正确的结果,而且我总能得到正确的结果。
问题在于被视为“非零”的值。在这种情况下:
SparseMatrix<int, RowMajor> A;
SparseMatrix<int, RowMajor> B;
//Parsing and initializing matrix
SparseMatrix<int, RowMajor> result = A*B;
result.pruned();
cout << result.nonZeros();
nonZeros()
的结果是5,这是“正常”情况,因为Result只有5个非零值。
现在,让我们考虑一下这段代码:
SparseMatrix<int, RowMajor> A;
SparseMatrix<int, RowMajor> B;
//Parsing and initializing matrix
SparseMatrix<int, RowMajor> result = (A*B).pruned();
cout << result.nonZeros();
nonZeros()
的结果是6.我不明白为什么,这是the documentation上提供的语法。
现在最奇怪的部分是,在非常大的矩阵result = A*B; result.pruned()
上有时也会将0保存为nonZero,但是比我使用(A*B).pruned();
我有三个问题:
result = (A*B).pruned()
和result=A*B;result.pruned();
会针对nonZero值给出不同的结果(而不是有效结果,这两种情况都是正确的)?我正在使用Visual Studio Professional 2013和Eigen 3.3.2,使用DEBUG模式并定位WIN32。
感谢您的帮助。
编辑:使用VS2013的稀疏乘法基准,W32的DEBUG /释放模式(有或没有SSE2指令集,两种情况都相同);结果总是正确的,所以我不是在这里粘贴它,它没有带来任何信息。随着:
1 = SparseMatrix<int, RowMajor> resultA = A*B;
2 = SparseMatrix<int, RowMajor> resultB = (A*B);resultB.pruned();
3 = SparseMatrix<int, RowMajor> resultC = (A*B).pruned();
案例1
Matrix A
2 0 0
0 2 0
0 0 2
Matrix B
5 3
0 1
2 8
预期值= 5
1 = 5
2 = 5
3 = 6
案例2 矩阵太大,here是文件
预期值= 0
1 = 1444
2 = 1444
3 = 0
正如您所看到的,根据输入和我调用函数的方式,结果是否优化,并且1,2或3都不适用于每种情况。
EDIT²:问题由ggael解决方案解决(谢谢)。
答案 0 :(得分:1)
我之前的回答(下面)错了。问题已修复there。
这是因为你的目标是win32,因此你正在打击 FPU寄存器扩展精度的经典问题。通过 默认情况下,
pruned
删除严格等于0的条目,但是 对于FPU,可能只有在非零后才变为零 被从寄存器复制到内存。更新编译器标志 要么瞄准SSE2指令集,要么杀死额外的FPU 精度。