From 80e18f583d30f469778d4e48afa47a04a64d63b4 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Tue, 13 Oct 2026 13:00:17 -0400 Subject: [PATCH 1/2] Avoid boxing the views captured by the threaded BLAS multiplication `Chead`, `Ahead` and `Bhead` are assigned in both branches of `_threaded_blas_mul!` and captured by the closure of `Threads.@spawn`, which makes Julia box them. These boxes are allocated whenever the function is called, also when it takes the single-threaded path. Interpolating the variables into `Threads.@spawn` avoids capturing them. Co-Authored-By: Claude Opus 5.5 --- src/linalg.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linalg.jl b/src/linalg.jl index c5befd1..4a1bbbe 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -148,7 +148,7 @@ function _threaded_blas_mul!( end nthreads1 = nthreads >> 1 nthreads2 = nthreads - nthreads1 - t = Threads.@spawn _threaded_blas_mul!(Chead, Ahead, CA, Bhead, CB, α, β, nthreads1) + t = Threads.@spawn _threaded_blas_mul!($Chead, $Ahead, CA, $Bhead, CB, α, β, nthreads1) _threaded_blas_mul!(Ctail, Atail, CA, Btail, CB, α, β, nthreads2) wait(t) return C From 4a045f24140dfb109fc586593576cc42ef04ccdc Mon Sep 17 00:00:00 2001 From: lkdvos Date: Wed, 14 Oct 2026 17:21:40 -0400 Subject: [PATCH 2/2] Test that BLAS multiplication with StridedView does not allocate Co-Authored-By: Claude Opus 5.5 --- test/blasmultests.jl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/blasmultests.jl b/test/blasmultests.jl index 45a30f2..af62bf0 100644 --- a/test/blasmultests.jl +++ b/test/blasmultests.jl @@ -96,3 +96,18 @@ end C1 = StridedView(copy(C)) @test mul!(C, A, B, α, β) ≈ mul!(C1, A1, B1, α, β) end + +# small enough to never be split over threads, such that no tasks need to be spawned +blasmul_allocations(C, A, B, α, β) = @allocated mul!(C, A, B, α, β) +@testset "Matrix multiplication with StridedView does not allocate: $T" for T in (Float64, ComplexF64) + d = 8 + A = StridedView(rand(T, (d, d))) + B = StridedView(rand(T, (d, d))) + C = StridedView(rand(T, (d, d))) + α = rand(T) + β = rand(T) + for op1 in (identity, conj, transpose, adjoint), op2 in (identity, conj, transpose, adjoint) + blasmul_allocations(C, op1(A), op2(B), α, β) # compile + @test blasmul_allocations(C, op1(A), op2(B), α, β) == 0 + end +end