|
467 | 467 |
|
468 | 468 |
|
469 | 469 | ## matrix multiplication |
| 470 | + |
| 471 | +# GPU-backed members of Base's StridedArray union match LinearAlgebra's BLAS methods, |
| 472 | +# but cannot be converted to host pointers. Route them to the generic GPU kernels. |
| 473 | +const StridedGPUSubArray{T,N} = Base.StridedSubArray{T,N,<:AbstractGPUArray} |
| 474 | +const AnyStridedGPUArray{T,N} = Union{AbstractGPUArray{T,N},StridedGPUSubArray{T,N}} |
| 475 | +const AnyStridedGPUVector{T} = AnyStridedGPUArray{T,1} |
| 476 | +const AnyStridedGPUMatrix{T} = AnyStridedGPUArray{T,2} |
| 477 | +const AnyStridedGPUVecOrMat{T} = Union{AnyStridedGPUVector{T},AnyStridedGPUMatrix{T}} |
| 478 | +const AnyStridedGPUMatrixOperand{T} = Union{ |
| 479 | + AnyStridedGPUMatrix{T}, |
| 480 | + Adjoint{T,<:AnyStridedGPUMatrix{T}}, |
| 481 | + Transpose{T,<:AnyStridedGPUMatrix{T}}, |
| 482 | + Symmetric{T,<:AnyStridedGPUMatrix{T}}, |
| 483 | + Hermitian{T,<:AnyStridedGPUMatrix{T}}, |
| 484 | +} |
| 485 | +const AnyStridedGPUVecOrMatOperand{T} = Union{ |
| 486 | + AnyStridedGPUVector{T}, |
| 487 | + AnyStridedGPUMatrixOperand{T}, |
| 488 | +} |
| 489 | + |
| 490 | +has_strided_gpu_view(As...) = |
| 491 | + any(A -> LinearAlgebra._unwrap(A) isa StridedGPUSubArray, As) |
| 492 | + |
| 493 | +# Intercept before LinearAlgebra unwraps operands and dispatches to backend BLAS methods. The |
| 494 | +# signatures also cover view-free products to avoid overlapping methods for each possible view |
| 495 | +# position; those calls are sent back through LinearAlgebra's original implementation. |
| 496 | +@static if VERSION < v"1.11" |
| 497 | +function LinearAlgebra.mul!(C::AnyStridedGPUVector, A::AnyStridedGPUMatrixOperand, |
| 498 | + B::AnyStridedGPUVector, a::Number, b::Number) |
| 499 | + if has_strided_gpu_view(C, A, B) |
| 500 | + return generic_matmatmul!(C, A, B, a, b) |
| 501 | + end |
| 502 | + invoke(LinearAlgebra.mul!, |
| 503 | + Tuple{AbstractVector,LinearAlgebra.AbstractVecOrMat,AbstractVector,Number,Number}, |
| 504 | + C, A, B, a, b) |
| 505 | +end |
| 506 | + |
| 507 | +function LinearAlgebra.mul!(C::AnyStridedGPUMatrix, A::AnyStridedGPUVecOrMatOperand, |
| 508 | + B::AnyStridedGPUVecOrMatOperand, a::Number, b::Number) |
| 509 | + if has_strided_gpu_view(C, A, B) |
| 510 | + return generic_matmatmul!(C, A, B, a, b) |
| 511 | + end |
| 512 | + invoke(LinearAlgebra.mul!, |
| 513 | + Tuple{AbstractMatrix,LinearAlgebra.AbstractVecOrMat, |
| 514 | + LinearAlgebra.AbstractVecOrMat,Number,Number}, |
| 515 | + C, A, B, a, b) |
| 516 | +end |
| 517 | +else |
| 518 | +function LinearAlgebra._mul!(C::AnyStridedGPUVector, A::AnyStridedGPUMatrixOperand, |
| 519 | + B::AnyStridedGPUVector, a::Number, b::Number) |
| 520 | + if has_strided_gpu_view(C, A, B) |
| 521 | + return generic_matmatmul!(C, A, B, a, b) |
| 522 | + end |
| 523 | + invoke(LinearAlgebra._mul!, |
| 524 | + Tuple{AbstractVector,LinearAlgebra.AbstractVecOrMat,AbstractVector,Number,Number}, |
| 525 | + C, A, B, a, b) |
| 526 | +end |
| 527 | + |
| 528 | +function LinearAlgebra._mul!(C::AnyStridedGPUMatrix, A::AnyStridedGPUVecOrMatOperand, |
| 529 | + B::AnyStridedGPUVecOrMatOperand, a::Number, b::Number) |
| 530 | + if has_strided_gpu_view(C, A, B) |
| 531 | + return generic_matmatmul!(C, A, B, a, b) |
| 532 | + end |
| 533 | + invoke(LinearAlgebra._mul!, |
| 534 | + Tuple{AbstractMatrix,LinearAlgebra.AbstractVecOrMat, |
| 535 | + LinearAlgebra.AbstractVecOrMat,Number,Number}, |
| 536 | + C, A, B, a, b) |
| 537 | +end |
| 538 | +end |
| 539 | + |
470 | 540 | # legacy method |
471 | 541 | generic_matmatmul!(C::AbstractArray, A::AbstractArray, B::AbstractArray, a::Number, b::Number) = |
472 | 542 | generic_matmatmul!(C, A, B, MulAddMul(a, b)) |
@@ -500,19 +570,19 @@ function generic_matmatmul!(C::AbstractArray{R}, A::AbstractArray{T}, B::Abstrac |
500 | 570 | end |
501 | 571 |
|
502 | 572 | @static if !isdefined(LinearAlgebra, Symbol("@stable_muladdmul")) # @stable_muladdmul was added in 1.12 |
503 | | -function LinearAlgebra.generic_matvecmul!(C::AbstractGPUVector, tA::AbstractChar, A::AbstractGPUMatrix, B::AbstractGPUVector, _add::MulAddMul = MulAddMul()) |
| 573 | +function LinearAlgebra.generic_matvecmul!(C::AnyStridedGPUVector, tA::AbstractChar, A::AnyStridedGPUMatrix, B::AnyStridedGPUVector, _add::MulAddMul = MulAddMul()) |
504 | 574 | generic_matmatmul!(C, wrap(A, tA), B, _add) |
505 | 575 | end |
506 | 576 |
|
507 | | -function LinearAlgebra.generic_matmatmul!(C::AbstractGPUVecOrMat, tA, tB, A::AbstractGPUVecOrMat, B::AbstractGPUVecOrMat, _add::MulAddMul=MulAddMul()) |
| 577 | +function LinearAlgebra.generic_matmatmul!(C::AnyStridedGPUVecOrMat, tA, tB, A::AnyStridedGPUVecOrMat, B::AnyStridedGPUVecOrMat, _add::MulAddMul=MulAddMul()) |
508 | 578 | generic_matmatmul!(C, wrap(A, tA), wrap(B, tB), _add) |
509 | 579 | end |
510 | 580 | else |
511 | | -function LinearAlgebra.generic_matvecmul!(C::AbstractGPUVector, tA::AbstractChar, A::AbstractGPUMatrix, B::AbstractGPUVector, a::Number, b::Number) |
| 581 | +function LinearAlgebra.generic_matvecmul!(C::AnyStridedGPUVector, tA::AbstractChar, A::AnyStridedGPUMatrix, B::AnyStridedGPUVector, a::Number, b::Number) |
512 | 582 | LinearAlgebra.@stable_muladdmul generic_matmatmul!(C, wrap(A, tA), B, MulAddMul(a, b)) |
513 | 583 | end |
514 | 584 |
|
515 | | -function LinearAlgebra.generic_matmatmul!(C::AbstractGPUVecOrMat, tA, tB, A::AbstractGPUVecOrMat, B::AbstractGPUVecOrMat, a::Number, b::Number) |
| 585 | +function LinearAlgebra.generic_matmatmul!(C::AnyStridedGPUVecOrMat, tA, tB, A::AnyStridedGPUVecOrMat, B::AnyStridedGPUVecOrMat, a::Number, b::Number) |
516 | 586 | LinearAlgebra.@stable_muladdmul generic_matmatmul!(C, wrap(A, tA), wrap(B, tB), MulAddMul(a, b)) |
517 | 587 | end |
518 | 588 | end |
@@ -556,22 +626,22 @@ end |
556 | 626 | @static if VERSION ≥ v"1.12.0-rc" |
557 | 627 | # we need to use the generic wrapper to avoid dispatch to the 2x2or3x3 method |
558 | 628 | using LinearAlgebra: generic_matmatmul_wrapper!, BlasFlag |
559 | | - function LinearAlgebra.generic_matmatmul_wrapper!(C::AbstractGPUMatrix{T}, tA::AbstractChar, tB::AbstractChar, A::AbstractGPUVecOrMat{T}, B::AbstractGPUVecOrMat{T}, alpha::Number, beta::Number, val::LinearAlgebra.BlasFlag.SyrkHerkGemm) where {T} |
| 629 | + function LinearAlgebra.generic_matmatmul_wrapper!(C::AnyStridedGPUMatrix{T}, tA::AbstractChar, tB::AbstractChar, A::AnyStridedGPUVecOrMat{T}, B::AnyStridedGPUVecOrMat{T}, alpha::Number, beta::Number, val::LinearAlgebra.BlasFlag.SyrkHerkGemm) where {T} |
560 | 630 | LinearAlgebra.generic_matmatmul!(C, tA, tB, A, B, alpha, beta) |
561 | 631 | end |
562 | 632 | # Symmetric/Hermitian inputs with BLAS eltypes would otherwise dispatch to BLAS.symm!/ |
563 | 633 | # hemm!: GPU arrays are DenseArrays, so they match the StridedMatrix{<:BlasFloat} methods |
564 | | - function LinearAlgebra.generic_matmatmul_wrapper!(C::AbstractGPUMatrix{T}, tA::AbstractChar, tB::AbstractChar, A::AbstractGPUVecOrMat{T}, B::AbstractGPUVecOrMat{T}, alpha::Number, beta::Number, val::LinearAlgebra.BlasFlag.SymmHemmGeneric) where {T} |
| 634 | + function LinearAlgebra.generic_matmatmul_wrapper!(C::AnyStridedGPUMatrix{T}, tA::AbstractChar, tB::AbstractChar, A::AnyStridedGPUVecOrMat{T}, B::AnyStridedGPUVecOrMat{T}, alpha::Number, beta::Number, val::LinearAlgebra.BlasFlag.SymmHemmGeneric) where {T} |
565 | 635 | LinearAlgebra.generic_matmatmul!(C, tA, tB, A, B, alpha, beta) |
566 | 636 | end |
567 | 637 | # need to support mixed complex/real types too |
568 | 638 | #function LinearAlgebra.generic_matmatmul_wrapper!(C::AbstractGPUMatrix{Complex{T}}, tA::AbstractChar, tB::AbstractChar, A::AbstractGPUVecOrMat{Complex{T}}, B::AbstractGPUVecOrMat{T}, alpha::Number, beta::Number, val::V) where {T<:BlasReal, V<:LinearAlgebra.BlasFlag.SyrkHerkGemm} |
569 | 639 | # LinearAlgebra.generic_matmatmul!(C, tA, tB, A, B, alpha, beta) |
570 | 640 | #end |
571 | | - function LinearAlgebra.generic_matmatmul_wrapper!(C::AbstractGPUMatrix{Complex{T}}, tA::AbstractChar, tB::AbstractChar, A::AbstractGPUVecOrMat{Complex{T}}, B::AbstractGPUVecOrMat{T}, alpha::Number, beta::Number, val::Val{LinearAlgebra.BlasFlag.GEMM}) where T<:Union{Float32, Float64} |
| 641 | + function LinearAlgebra.generic_matmatmul_wrapper!(C::AnyStridedGPUMatrix{Complex{T}}, tA::AbstractChar, tB::AbstractChar, A::AnyStridedGPUVecOrMat{Complex{T}}, B::AnyStridedGPUVecOrMat{T}, alpha::Number, beta::Number, val::Val{LinearAlgebra.BlasFlag.GEMM}) where T<:Union{Float32, Float64} |
572 | 642 | LinearAlgebra.generic_matmatmul!(C, tA, tB, A, B, alpha, beta) |
573 | 643 | end |
574 | | - function LinearAlgebra.generic_matmatmul_wrapper!(C::AbstractGPUMatrix{Complex{T}}, tA::AbstractChar, tB::AbstractChar, A::AbstractGPUVecOrMat{T}, B::AbstractGPUVecOrMat{Complex{T}}, alpha::Number, beta::Number, val::Val{LinearAlgebra.BlasFlag.GEMM}) where T<:Union{Float32, Float64} |
| 644 | + function LinearAlgebra.generic_matmatmul_wrapper!(C::AnyStridedGPUMatrix{Complex{T}}, tA::AbstractChar, tB::AbstractChar, A::AnyStridedGPUVecOrMat{T}, B::AnyStridedGPUVecOrMat{Complex{T}}, alpha::Number, beta::Number, val::Val{LinearAlgebra.BlasFlag.GEMM}) where T<:Union{Float32, Float64} |
575 | 645 | LinearAlgebra.generic_matmatmul!(C, tA, tB, A, B, alpha, beta) |
576 | 646 | end |
577 | 647 | # Julia 1.12 introduced generic_mul! for scalar * array operations |
|
0 commit comments