From 11c0d7fb34066bf1bd4b77303d0bd5e921b64a5f Mon Sep 17 00:00:00 2001 From: Christian <28689358+christiangnrd@users.noreply.github.com> Date: Tue, 20 Oct 2026 11:01:25 -0300 Subject: [PATCH 1/2] Copy only the diagonal in copyto!(::Diagonal, ::Diagonal) for GPU arrays The generic AnyGPUArray copyto! is more specific than LinearAlgebra's Diagonal method, so it launched a kernel over all n^2 entries calling setindex!(::Diagonal). On Julia 1.10 that method's error path eagerly builds a string, which POCL/SPIR-V rejects, breaking cholesky(::Diagonal) for JLArrays with KA 0.10. Co-Authored-By: Claude Opus 5.5 (1M context) --- src/host/linalg.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/host/linalg.jl b/src/host/linalg.jl index a198c3de..3c6788e2 100644 --- a/src/host/linalg.jl +++ b/src/host/linalg.jl @@ -326,6 +326,14 @@ end Base.copy(D::Diagonal{T, <:AbstractGPUArray{T, N}}) where {T, N} = Diagonal(copy(D.diag)) +# copy only the diagonal; the generic `AnyGPUArray` method would launch a kernel over all +# n^2 entries, calling `setindex!(::Diagonal, ...)` whose error path isn't GPU-compatible +function Base.copyto!(D1::Diagonal{T, <:AbstractGPUArray{T, N}}, + D2::Diagonal{S, <:AbstractGPUArray{S, M}}) where {T, N, S, M} + copyto!(D1.diag, D2.diag) + return D1 +end + _isrealandpositive(x) = isreal(x) && real(x) > 0 function LinearAlgebra.cholesky!(D::Diagonal{<:Any, <:AbstractGPUArray}, From e04e6569584aa94e826f62f9c4e8da9e817cf0a9 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Tue, 27 Oct 2026 21:01:19 +0100 Subject: [PATCH 2/2] Test `copyto!` between GPU Diagonals Cover the method directly, including a conversion between element types, rather than only through `cholesky`. --- test/testsuite/linalg.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/testsuite/linalg.jl b/test/testsuite/linalg.jl index 0df896c7..6a3835b1 100644 --- a/test/testsuite/linalg.jl +++ b/test/testsuite/linalg.jl @@ -512,6 +512,18 @@ end @test collect(D) == collect(C) end + @testset "copyto! diagonal" begin + D = Diagonal(AT(rand(Float32, 10))) + C = Diagonal(AT(zeros(Float32, 10))) + @test copyto!(C, D) === C + @test C.diag isa AT + @test collect(C) == collect(D) + + D = Diagonal(AT(Int32.(1:10))) + copyto!(C, D) + @test collect(C) == Diagonal(Float32.(1:10)) + end + @testset "cholesky + Diagonal" begin n = 128 # Add one in order prevent failures due to random numbers being zero