-
-
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
Add spmv! to BLAS in stdlib/LinearAlgebra #34320
Conversation
496bb08
to
42577b2
Compare
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 looks great. Just one comment on the allowed signature, with relevance for the previous hpmv
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.
I think my previous concern on "enforcing 1-dimensionality" was void, so that's resolved. I'd suggest though to explain the packed format explicitly, since the link to the LAPACK page is rather indirect, one has to search on their webpage to get to the specific page. This might carry over to the hpmv
code.
stdlib/LinearAlgebra/src/blas.jl
Outdated
if length(AP) < Int64(N*(N+1)/2) | ||
throw(DimensionMismatch("Packed symmetric matrix A has size smaller than length(x) = $(N).")) | ||
end | ||
GC.@preserve x y AP spmv!(uplo, N, convert(T, α), AP, pointer(x), BlasInt(stride(x, 1)), convert(T, β), pointer(y), BlasInt(stride(y, 1))) |
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.
Do we need to preserve AP
explicitly? I guess it's referenced directly and not in danger of being gc'ed.
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.
Maybe I'm too cautious here due to lack of deep GC knowledge, so looking at the other @GC.preserve statements in blas.jl
I do not see any crucial difference and reason to drop AP from the preserve statement. Could you maybe explain this a bit more or point out the the thing that I'm missing?
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.
IIUC, then only those are listed which are wrapped by a pointer(...)
. You could double-check if that's the case, but that was my understanding.
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.
IIUC, then only those are listed which are wrapped by a
pointer(...)
. You could double-check if that's the case, but that was my understanding.
So if I were to drop the pointer(...)
around x and y as well then the whole @GC.preserve might be unnecessary? If true this might be tempting to apply to have a more clean API. :)
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.
Possibly following here a pattern similar to that in the symv!
implementation strengthens your reading so removing the @GC.preserve
alltogether might be good to go. If you are also okay with it I will apply this modification as well.
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.
On the other hand maybe the following is a non-issue but wherever we have a @GC.preserve
we also have Union{DenseArray,...} or Union{Unitrange,...} or Union{.., ...}. Maybe these are unrelated but they do appear together so the removal of @GC.preserve
would induce to suggest to remove pointer(...)
and GC.preserve
from all those functions. I don't know whether this is wise as people might have put it this way for a reason unknown to me at the moment.
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.
Probably there is no harm in keeping AP
here, so unless someone comes by and helps in resolving this aspect, this should not keep us from merging this.
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.
I am planning other similar pull requests. Would it be okay in your opinion to ask someone within this comment thread whether to use the @GC.preserve
to ease further development?
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.
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.
It's better just to pass the arrays, see #34783.
I agree that part of the docstring changes and more nice tests are necessary and would like to apply them to |
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.
I'd suggest we work on this until spmv!
is perfect, and then edit hpmv!
accordingly in another PR. I believe there are only mild adoptions necessary, like the restriction to Real
, and some small work on the docstrings, so there is an end in sight. We can raise the GC.gc
issue in the next PR again, unless someone comes by and helps out with expertise here.
stdlib/LinearAlgebra/src/blas.jl
Outdated
if length(AP) < Int64(N*(N+1)/2) | ||
throw(DimensionMismatch("Packed symmetric matrix A has size smaller than length(x) = $(N).")) | ||
end | ||
GC.@preserve x y AP spmv!(uplo, N, convert(T, α), AP, pointer(x), BlasInt(stride(x, 1)), convert(T, β), pointer(y), BlasInt(stride(y, 1))) |
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.
Probably there is no harm in keeping AP
here, so unless someone comes by and helps in resolving this aspect, this should not keep us from merging this.
42577b2
to
116ed29
Compare
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 is shaping up nicely, just some minor polishing and this may serve as the role model for a minor hpmv!
"fix".
stdlib/LinearAlgebra/src/blas.jl
Outdated
(:sspmv_, :Float32)) | ||
@eval begin | ||
function spmv!(uplo::AbstractChar, | ||
n::BlasInt, |
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.
I guess we kind of figured out in #34360 that this should be Integer
.
stdlib/LinearAlgebra/src/blas.jl
Outdated
if length(AP) < Int64(N*(N+1)/2) | ||
throw(DimensionMismatch("Packed symmetric matrix A has size smaller than length(x) = $(N).")) | ||
end | ||
GC.@preserve x y AP spmv!(uplo, BlasInt(N), convert(T, α), AP, pointer(x), BlasInt(stride(x, 1)), convert(T, β), pointer(y), BlasInt(stride(y, 1))) |
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.
... and here no BlasInt(N)
etc. conversions
stdlib/LinearAlgebra/test/blas.jl
Outdated
# Define the inputs and outputs of spmv!, y = α*A*x+β*y | ||
α = rand(elty) | ||
M = rand(elty, n, n) | ||
A = Symmetric(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.
I would write
AL = Symmetric(M, :L)
AU = Symmetric(M, :U)
...
stdlib/LinearAlgebra/test/blas.jl
Outdated
β = rand(elty) | ||
y = rand(elty, n) | ||
|
||
y_result_julia = α*A*x+β*y |
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.
then
y_result_julia = α*AL*x+β*y
...
stdlib/LinearAlgebra/test/blas.jl
Outdated
AP = typeof(A[1,1])[] | ||
for j in 1:n | ||
for i in j:n | ||
push!(AP, A[i,j]) |
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.
...
push!(AP, M[i,j])
and AP = typeof(M[1,1])[]
(even though that doesn't matter at all, just for clarity where we take types from)...
stdlib/LinearAlgebra/test/blas.jl
Outdated
@test y_result_julia≈y_result_blas_lower | ||
|
||
# Create upper triangular packing of A | ||
AP = typeof(A[1,1])[] |
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.
... and analogous changes here, with a recomputed
y_result_julia = α*AU*x+β*y
116ed29
to
76dfed6
Compare
@yuyichao Could you please help us and take a look at the @iolaszlo Could you maybe rebase your branch on current master. That might help to resolve some of the (otherwise unrelated) test failures. |
62044c6
to
e6828c8
Compare
Follow the syntax, docstring and testing conventions elaborated in JuliaLang#34320.
Follow the syntax, docstring and testing conventions elaborated in JuliaLang#34320.
Follow the syntax, docstring and testing conventions elaborated in JuliaLang#34320.
It would be great to get this PR in, and to learn about how to use |
+1 to get the PR in, but we need someone else to chime in on |
e6828c8
to
a602df6
Compare
Follow the syntax, docstring and testing conventions elaborated in JuliaLang#34320.
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.
Thanks for your stamina @iolaszlo! 😃
On win32, the |
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.
Just a few minor comments, but looks good to me other than that.
stdlib/LinearAlgebra/src/blas.jl
Outdated
throw(DimensionMismatch("Packed symmetric matrix A has size smaller than length(x) = $(N).")) | ||
end | ||
spmv!(uplo, N, convert(T, α), AP, x, stride(x, 1), convert(T, β), y, stride(y, 1)) | ||
y |
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.
...then you can leave it out here. I prefer explicit return spmv!...
but it's not required.
stdlib/LinearAlgebra/test/blas.jl
Outdated
|
||
y_result_blas_upper = copy(y) | ||
BLAS.spmv!('U', α, AP, x, β, y_result_blas_upper) | ||
@test y_result_julia_upper≈y_result_blas_upper |
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.
@test y_result_julia_upper≈y_result_blas_upper | |
@test y_result_julia_upper ≈ y_result_blas_upper |
stdlib/LinearAlgebra/test/blas.jl
Outdated
@test y_result_julia_lower≈y_result_blas_lower | ||
|
||
|
||
y_result_julia_upper = α*AU*x+β*y |
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.
y_result_julia_upper = α*AU*x+β*y | |
y_result_julia_upper = α*AU*x + β*y |
stdlib/LinearAlgebra/test/blas.jl
Outdated
β = rand(elty) | ||
y = rand(elty, n) | ||
|
||
y_result_julia_lower = α*AL*x+β*y |
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.
y_result_julia_lower = α*AL*x+β*y | |
y_result_julia_lower = α*AL*x + β*y |
stdlib/LinearAlgebra/src/blas.jl
Outdated
if N != length(y) | ||
throw(DimensionMismatch("x has length $(N), but y has length $(length(y))")) | ||
end | ||
if length(AP) < Int64(N*(N+1)/2) |
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.
if length(AP) < Int64(N*(N+1)/2) | |
if 2*length(AP) < N*(N + 1) |
a602df6
to
947cd03
Compare
CI failures are in Distributed and Sockets, respectively. I'd say unrelated. |
@dkarrasch Thank you for the constructive review process. |
No description provided.