EIGEN:稀疏矩阵乘法不产生修剪结果
EIGEN : Sparse matrix multiplication not producing a pruned result
我将 EIGEN 用于稀疏矩阵优化和函数。一切都很好 "working",除了在某些情况下,我无法弄清楚这种情况。
事情是这样的:
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
如您所见,这是正确的结果,而且我总是得到正确的结果。
问题是关于被视为 "Non Zero" 的值。在这种情况下:
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,这是 "normal" 的情况,因为结果只有 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 保存为非零,但比我使用 (A*B).pruned();
我有三个问题:
- 为什么
result = (A*B).pruned()
和 result=A*B;result.pruned();
给出关于非零值的不同结果(而不是有效结果,这在两种情况下都是正确的)?
- 为什么产品的 0 值有时不被视为零值?
- 你的结果和我一样吗?
我正在使用 Visual Studio Professional 2013 和 Eigen 3.3.2,使用 DEBUG 模式并针对 WIN32。
感谢您的帮助。
编辑: VS2013 的稀疏乘法基准,W32 的 DEBUG/Release 模式(有或没有 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();
案例一
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
案例二
矩阵太大,here是文件
期望值 = 0
1 = 1444
2 = 1444
3 = 0
如您所见,根据输入和我调用函数的方式,结果是否优化,并且 none of 1, 2 or 3 在每种情况下都有效。
EDIT² : ggael 解决方案解决了问题(感谢)。
我之前的回答(如下)是错误的。问题已修复 there.
This is because you are targeting win32 and thus you are hitting
classical issues with the extended precision of the FPU registers. By
default, pruned
remove entries that are strictly equal to 0, but
with the FPU, it could be that a non zero becomes zero only after
being copied from its register to memory. Update your compiler flags
to either target SSE2 instruction set, or to kill the extra FPU
precision.
我将 EIGEN 用于稀疏矩阵优化和函数。一切都很好 "working",除了在某些情况下,我无法弄清楚这种情况。
事情是这样的:
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
如您所见,这是正确的结果,而且我总是得到正确的结果。
问题是关于被视为 "Non Zero" 的值。在这种情况下:
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,这是 "normal" 的情况,因为结果只有 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 保存为非零,但比我使用 (A*B).pruned();
我有三个问题:
- 为什么
result = (A*B).pruned()
和result=A*B;result.pruned();
给出关于非零值的不同结果(而不是有效结果,这在两种情况下都是正确的)? - 为什么产品的 0 值有时不被视为零值?
- 你的结果和我一样吗?
我正在使用 Visual Studio Professional 2013 和 Eigen 3.3.2,使用 DEBUG 模式并针对 WIN32。
感谢您的帮助。
编辑: VS2013 的稀疏乘法基准,W32 的 DEBUG/Release 模式(有或没有 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();
案例一
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
案例二 矩阵太大,here是文件
期望值 = 0
1 = 1444
2 = 1444
3 = 0
如您所见,根据输入和我调用函数的方式,结果是否优化,并且 none of 1, 2 or 3 在每种情况下都有效。
EDIT² : ggael 解决方案解决了问题(感谢)。
我之前的回答(如下)是错误的。问题已修复 there.
This is because you are targeting win32 and thus you are hitting classical issues with the extended precision of the FPU registers. By default,
pruned
remove entries that are strictly equal to 0, but with the FPU, it could be that a non zero becomes zero only after being copied from its register to memory. Update your compiler flags to either target SSE2 instruction set, or to kill the extra FPU precision.