0
votes

I'm using EIGEN for the sparse matrix optimizations and functions. Everything is "working" fine, except in some case and I can't figure this case out.

Here is the thing :

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 

As you can see, this is the right result, and I'm always having the right result.

The problem is about the values considered as "Non Zero". In this case :

SparseMatrix<int, RowMajor> A;
SparseMatrix<int, RowMajor> B;
//Parsing and initializing matrix
SparseMatrix<int, RowMajor> result = A*B;
result.pruned();
cout << result.nonZeros();

The result of nonZeros() is 5, which is the "normal" case, since Result got only 5 non Zero values. Now, let's consider this code :

SparseMatrix<int, RowMajor> A;
SparseMatrix<int, RowMajor> B;
//Parsing and initializing matrix
SparseMatrix<int, RowMajor> result = (A*B).pruned();
cout << result.nonZeros();

The result of nonZeros() is 6. I do not understand why, this is the syntax available on the documentation.

And now the strangest part is that on very large matrix result = A*B; result.pruned() is sometimes ALSO saving 0 as nonZero, but less than if I used (A*B).pruned();

I got three questions :

  • Why are result = (A*B).pruned() and result=A*B;result.pruned(); giving different results concerning nonZero values (and not effective result, which is right in both case)?
  • Why are 0 values from a product sometimes not considered as Zero Values?
  • Are you having the same result than me?

I'm using Visual Studio Professional 2013 and Eigen 3.3.2, using DEBUG mode and targeting WIN32.

Thanks for your help.

EDIT : Benchmark of sparse multiplication with VS2013, DEBUG/Release mode for W32 (With or without SSE2 instruction set, same results in both case); the result is always the right one so i'm not pasting it here, it's not bringing any information. With :

1 = SparseMatrix<int, RowMajor> resultA = A*B;

2 = SparseMatrix<int, RowMajor> resultB = (A*B);resultB.pruned();

3 = SparseMatrix<int, RowMajor> resultC = (A*B).pruned();

Case 1

Matrix A
2 0 0
0 2 0
0 0 2

Matrix B
5 3
0 1
2 8

Expected value = 5

1 = 5

2 = 5

3 = 6

Case 2 Matrix are too large, here is the file

Expected value = 0

1 = 1444

2 = 1444

3 = 0

As you can see, depending both on the input and the way I'm calling functions, the result is optimized or not, and none of 1, 2 or 3 are working in every case.

EDIT² : Problem fixed by ggael solution (thanks).

1

1 Answers

1
votes

My previous answer (below) was wrong. Problem fixed 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.