-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
improve performance for Matrix -> SparseMatrix #26334
Conversation
@@ -376,6 +376,27 @@ function SparseMatrixCSC{Tv,Ti}(M::AbstractMatrix) where {Tv,Ti} | |||
eltypeTvV = convert(Vector{Tv}, V) | |||
return sparse_IJ_sorted!(eltypeTiI, eltypeTiJ, eltypeTvV, size(M)...) | |||
end | |||
function SparseMatrixCSC{Tv,Ti}(M::Matrix) where {Tv,Ti} | |||
nz = count(!equalto(0), M) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This count is needed to avoid using push!
which unfortunately is slow due to its overhead (#24909).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't you want !equalto(zero(Tv))
here? Thinking about matrices with SVector entries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -376,6 +376,27 @@ function SparseMatrixCSC{Tv,Ti}(M::AbstractMatrix) where {Tv,Ti} | |||
eltypeTvV = convert(Vector{Tv}, V) | |||
return sparse_IJ_sorted!(eltypeTiI, eltypeTiJ, eltypeTvV, size(M)...) | |||
end | |||
function SparseMatrixCSC{Tv,Ti}(M::Matrix) where {Tv,Ti} | |||
nz = count(!equalto(0), M) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tv
might not be concrete, and the matrix may contain missing
or (more realistically) be have SVector entries.
Maybe nz = count(x->true===iszero(x), M)
? That way we only lose type information of zeros.
Not sure about performance implications (sorry for double-posting, failed at github-ui).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this is a pure performance improvement over the current function which uses findnz
which does nnzA = count(t -> t != 0, A)
and if Aij != 0
. Changing the sparse matrix library to work more complicated elements is out of scope for this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that equalto
uses isequal
, so this will change the behavior for -0.0
.
end | ||
return SparseMatrixCSC(size(M, 1), size(M, 2), colptr, rowval, nzval) | ||
end | ||
|
||
# converting from SparseMatrixCSC to other matrix types | ||
function Matrix(S::SparseMatrixCSC{Tv}) where Tv |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi.
You are using
size(M, 2)
3 times and
size(M,1)
two times. Would not be faster to define two variables with those values and than use them? Or the interpreter can optimize it anyway ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a valid comment. However, in this case, even if the compiler doesn't optimize it away, the time to access these fields should be completely insignificant to the rest of the code. The question here is if it makes the code more legible to store them in m
and n
, for example. I'm not sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed! Thanks for your answer. Sometimes I wonder if the loops can be (somehow) optimized in those cases.
Is there any reason why we wouldn't use this implementation for all |
There are so many types of matrices I am not sure exactly what you need to fulfill the API. For example, this assumes column major and that indices starts at 1 etc. I was just playing it safe with |
Extending to |
Benchmark (
sparse2
is PR):