Is assign DenseMatrix to Compressed one is effective?
// Suppose I have dense matrix
blaze::DenseMatrix<double> A;
// ... Fill matrix A ...
// and I want to assign it to compressed matrix
blaze::CompressedMatrix<double> B = A;
Is this operation will be effective? How I could make it more effective?
Thanks
Comments (4)
-
-
reporter I am concerned about the ambiguity of comparing to zero for a floating point. And compressed matrix size reserversion.
How you think is it make sense to make conversion dense to compressed matrix function with custom zero threshold?
-
Hi Victor!
I understand your concerns. By default, Blaze only filters the values that are exactly zero (i.e.
0.0F
). All other values are copied into the sparse matrix:DynamicMatrix<float> A { { 1.0F, 1E-9F, 0.0F } , { 1E-9F, 2.0F, 1E-9F } , { 0.0F, 1E-9F, 3.0F } }; CompressedMatrix<float> B( A ); std::cerr << "\n" << " B =\n" << B << "\n" << " B.nonZeros() = " << B.nonZeros() << "\n" // Prints 7 << " B.capacity() = " << B.capacity() << "\n" // Prints 7 << "\n";
In order to also filter all values below a certain threshold, you can use the
map()
function:DynamicMatrix<float> A { { 1.0F, 1E-9F, 0.0F } , { 1E-9F, 2.0F, 1E-9F } , { 0.0F, 1E-9F, 3.0F } }; const float threshold( 1E-8F ); CompressedMatrix<float> B( map( A, [threshold]( float f ){ return f < threshold ? 0.0F : f; } ) ); std::cerr << "\n" << " B =\n" << B << "\n" << " B.nonZeros() = " << B.nonZeros() << "\n" // Prints 3 << " B.capacity() = " << B.capacity() << "\n" // Prints 7 (more than required, see below) << "\n";
The allocation of memory works similarly to the strategy in
std::vector
. When the capacity is depleted,CompressedMatrix
allocates new capacity for twice as many elements. There are two ways to control that. First, you can acquire the required amount of capacity up-front:DynamicMatrix<float> A { { 1.0F, 1E-9F, 0.0F } , { 1E-9F, 2.0F, 1E-9F } , { 0.0F, 1E-9F, 3.0F } }; CompressedMatrix<float> B( rows(A), columns(A), nonZeros(A) ); // Pre-allocate memory for 3 non-zero elements const float threshold( 1E-8F ); B = map( A, [threshold]( float f ){ return f < threshold ? 0.0F : f; } ); std::cerr << "\n" << " B =\n" << B << "\n" << " B.nonZeros() = " << B.nonZeros() << "\n" // Prints 3 << " B.capacity() = " << B.capacity() << "\n" // Prints 3 << "\n";
Alternatively you can call
shrinkToFit()
after the copy operation (again, similar tostd::vector
):DynamicMatrix<float> A { { 1.0F, 1E-9F, 0.0F } , { 1E-9F, 2.0F, 1E-9F } , { 0.0F, 1E-9F, 3.0F } }; const float threshold( 1E-8F ); CompressedMatrix<float> B( map( A, [threshold]( float f ){ return f < threshold ? 0.0F : f; } ) ); B.shrinkToFit(); // Re-allocates to adapt the capacity to the current requirements std::cerr << "\n" << " B =\n" << B << "\n" << " B.nonZeros() = " << B.nonZeros() << "\n" // Prints 3 << " B.capacity() = " << B.capacity() << "\n" // Prints 3 << "\n";
I hope this answers your questions,
Best regards,
Klaus!
-
- changed status to resolved
- Log in to comment
Hi Victor!
Yes, you can copy a dense matrix (row-major or column-major) to a sparse matrix (also row-major or column-major). In this operation Blaze only copies the non-zero elements of the dense matrix into the sparse matrix:
Blaze will perform this assignment as efficiently as possible. We are not aware of any way how to improve the performance of this operation, but we gladly accept any suggestion for improvement.
I hope this answers the question,
Best regards,
Klaus!