-
-
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
RFC: Fast mul! with Q matrices from QR factorizations. #31581
Conversation
Use BLAS' gemqrt! and ormqr! when performing mul! with Q matrices or their transpose.
stdlib/LinearAlgebra/src/qr.jl
Outdated
end | ||
|
||
function mul!(C::StridedVecOrMat{T}, Q::AbstractQ{T}, B::StridedVecOrMat{T}) where T<:BlasFloat | ||
check_dimensions(C, 'N', 'N', Q, B) |
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.
Is it necessary to check the dimensions here? Both copyto!
and two-argument lmul!
have checks so I wouldn't think it would be needed here.
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.
With StridedVecOrMat
s of BlasFloat
s, lmul!
calls LAPACK.gemqrt!
or LAPACK.ormqr!
directly. So it depends on whether these assume correct sizes already.
On a different note, there is also function lmul!(A::QRPackedQ, B::AbstractVecOrMat)
. Should we then also have the proposed mul!
methods here for abstract vectors or matrices?
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.
LAPACK.gemqrt!
and LAPACK.ormqr!
seem to check dimensions, but copyto!(A, B)
only checks that length(A) >= length(B)
which is less strict than the checks I have.
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.
Yes, thanks, I think that we should also support AbstractVecOrMat
. On a related note, I cannot understand thought why rmul!
requires StridedMatrix
while lmul!
does not, i.e.
function lmul!(A::QRPackedQ, B::AbstractVecOrMat)
function rmul!(A::StridedMatrix, adjQ::Adjoint{<:Any,<:QRPackedQ})
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 one wanted to have stricter checks, one could use copy!
instead of copyto!
, which requires equal axes. I couldn't find any use of copy!
in qr.jl
though. That sounds like there's no need for additional size checks then?
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.
Hm, it occurred to me that for mutating *mul!
functions you need memory to write into. So it could be that the destination arrays need to be strided, but for 3-arg mul!
, the source array could be abstract. Does that make sense for a general rule?
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.
@dkarrasch thanks I wasn't aware of copy!
. I will use that and remove the additional size checks.
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.
Well, I thought that since both the LAPACK functions and the generic Julian *mul!
functions do size checks, it would suffice to leave it to them and to use the more "generous" copyto!
(as suggested by @andreasnoack), independently of whether you go the LAPACK or the generic Julia route. Basically, leave everything as you have, but kick out size checks.
As suggested, I removed the size checks. Also, following @dkarrasch suggestion, I relaxed the type of the "input" of @dkarrasch I must say though that I do not understand what you meant by the following:
On a related note, I do not understand why |
What I meant was that for mutating versions, you require memory to write the result into. I assume that this is why you need a |
Consider the following example:
Same with |
Thanks alot @dkarrasch for the explanations! Following the suggestions above I relaxed the definitions of the newly-added methods to be: mul!(C::StridedVecOrMat{T}, Q::AbstractQ{T}, B::AbstractVecOrMat{T}) where {T}
mul!(C::StridedVecOrMat{T}, A::AbstractVecOrMat{T}, Q::AbstractQ{T}) where {T}
mul!(C::StridedVecOrMat{T}, adjQ::Adjoint{<:Any,<:AbstractQ{T}}, B::AbstractVecOrMat{T}) where {T}
mul!(C::StridedVecOrMat{T}, A::AbstractVecOrMat{T}, adjQ::Adjoint{<:Any,<:AbstractQ{T}}) where {T} However, the Test Failed at /Users/nrontsis/julia/stdlib/LinearAlgebra/test/ambiguous_exec.jl:4
Expression: detect_ambiguities(LinearAlgebra; imported=true, recursive=true) == []
Evaluated: Tuple{Method,Method}[(mul!(C::AbstractArray{T,2} where T, ... in LinearAlgebra at /Users/nrontsis/julia/usr/share/julia/stdlib/v1.2/LinearAlgebra/src/qr.jl:742)] == Any[]
ERROR: Error while loading expression starting at /Users/nrontsis/julia/stdlib/LinearAlgebra/test/ambiguous_exec.jl:4
caused by [exception 1]
There was an error during testing
method ambiguity: Test Failed at /Users/nrontsis/julia/stdlib/LinearAlgebra/test/matmul.jl:508 Any advice would be greatly appreciated. |
I have seen elsewhere in the code (or remember Andreas mention) that sometimes methods are split for vectors and matrices, like
etc., maybe that helps? EDIT: You generalized the method signature in commit 3dd2729, and didn't mention the issue before. So that could be an indication that this is indeed the issue. |
@dkarrasch thanks for the suggestion. Unfortunately it seems that splitting the methods to vectors and matrices did not resolve the method ambiguity. However, restricting all the inputs to be strided solved it. This is obviously not ideal, as, according to the discussion above, the second or third input to Regardless, I restricted the method definitions to only allow for strided inputs, so as to have a reference commit at which the tests pass. I have also updated the description of the issue to include a task list, hoping that this will facilitate the discussion. |
Good to know that there was a good reason for the strided requirement. After all, I think this should cover the regular use cases. Vectors that result from other multiplication processes will be likely strided anyway, and the |
Okay, in that case lets also restrict |
I'm not sure if we should add restrictions without immediate need. You could try to relax the |
Okay let's leave it as it is then. Do you think this is ready to be merged? |
I don't have authority to merge, but apparently I do have authority to approve, which I have just done. |
Purpose
Uses
LAPACK
'sgemqrt!
andormqr!
when performingmul!
withQ
matrices, ofQR
decompositions, or their transpose. Fixes JuliaLang/LinearAlgebra.jl#612. Acknowledged duplicate of #31163.Tasks list
mul!
methodslmul!/mul!
on non-strided arrays.Notes
No methods for
mul!
with a tranposedAbstractMatrix
/AbstractVector
input. This is because I could not find a way to perform this without extra memory allocation.