LinearAlgebra.gemv! vs BLAS.gemv!

I am trying to understand what julia uses in a call to mul! in the following example:

using LinearAlgebra
m,n = 10,5;
A = randn(m,n);
x = randn(n);
Ax = zeros(m);
@code_lowered mul!(Ax, A, x, true, false)
@code_lowered LinearAlgebra.gemv!('N', true, A, x, false, Ax)
@code_lowered BLAS.gemv!('N', true, A, x, false, Ax)
@code_llvm mul!(Ax, A, x, true, false)
@code_llvm LinearAlgebra.gemv!('N', true, A, x, false, Ax)
@code_llvm BLAS.gemv!('N', true, A, x, false, Ax)

julia> @code_lowered mul!(Ax, A, x, true, false)
CodeInfo(
1 ─      nothing
β”‚   %2 = LinearAlgebra.gemv!(y, 'N', A, x, alpha, beta)
└──      return %2
)
julia> @code_lowered @views LinearAlgebra.gemv!('N', true, A, x, false, Ax)
CodeInfo(
1 ─      nothing
β”‚   %2 = Base.replace_ref_begin_end!(x)
β”‚   %3 = Base._views(%2)
β”‚   %4 = Base.esc(%3)
└──      return %4
)
julia> @code_lowered @views BLAS.gemv!('N', true, A, x, false, Ax)
CodeInfo(
1 ─      nothing
β”‚   %2 = Base.replace_ref_begin_end!(x)
β”‚   %3 = Base._views(%2)
β”‚   %4 = Base.esc(%3)
└──      return %4
)
julia> LinearAlgebra.gemv! == LinearAlgebra.BLAS.gemv!
false

Repeating the above with @code_llvm instead of @code_lowered makes it seem that mul! calls LinearAlgebra.gemv! which is the same as BLAS.gemv! and LinearAlgebra.BLAS.gemv!. Is there a difference between LinearAlgebra.gemv! and LinearAlgebra.BLAS.gemv!? Guessing I have a simple misunderstanding for why LinearAlgebra.gemv! == LinearAlgebra.BLAS.gemv! is false.

Your use of @views is messing up things a bit in your examination.

A simpler way to see that they’re not the same is:

julia> length(methods(BLAS.gemv!))
4

julia> length(methods(LinearAlgebra.gemv!))
9
1 Like

Ah thanks, I messed up including @views in there. So now it is clear that mul! calls LinearAlgebra.gemv!. However, what is the difference between BLAS.gemv! and LinearAlgebra.gemv!? I see that LinearAlgebra.BLAS.gemv! == BLAS.gemv!.

LinearAlgebra.gemv! is defined here: https://github.com/JuliaLang/julia/blob/aef528d32a6291ce82452c3a1ff1fa56ccf17641/stdlib/LinearAlgebra/src/matmul.jl#L401-L478

As you can see, it’s a wrapper that does some argument checks et cetera before calling BLAS.gemv!, or in some cases another BLAS function or generic matmul implementation. LinearAlgebra has a lot of somewhat interrelated delegation mechanisms to make everything work smoothly, but if your arrays are BLAS compatible you will eventually end up in a BLAS function.

2 Likes