Skip to content

Matrix products with strided views of JLArrays error since JLArrays 0.3.2 ("Illegal conversion of a JLArray to a Ptr") #756

Description

@cossio

Since JLArrays v0.3.2, any * / mul! involving a strided SubArray of a JLArray with a BLAS-eligible eltype errors. MWE on Julia 1.12.6, JLArrays v0.3.2:

using JLArrays, LinearAlgebra
JLArrays.allowscalar(false)

A = JLArray(randn(4, 3))
B = JLArray(randn(4, 5))

view(A, 1:2, :)' * view(B, 1:2, :)
# ERROR: Illegal conversion of a JLArray to a Ptr
# Stacktrace: ... gemm!(...) @ LinearAlgebra.BLAS

The same happens for dense' * view, view' * dense, view' * vector, and mul! with any strided-view operand. On JLArrays v0.3.1 all of these "worked".

What changed

SubArrays of a JLArray with contiguous-ish indices belong to Base's StridedArray union (since AbstractGPUArray <: DenseArray), so for BLAS eltypes LinearAlgebra routes these products to BLAS gemm!/gemv!, which calls unsafe_convert(::Type{Ptr}, ...):

  • On v0.3.1, Base.unsafe_convert(Ptr{T}, ::JLArray) silently returned a pointer into the host-backed buffer, so the products ran CPU BLAS on the emulation array — numerically correct, but exactly the implicit CPU ccall that JLArrays is meant to catch.
  • On v0.3.2, the new guard (error("Illegal conversion of a JLArray to a Ptr"), added alongside the "Pointer access is only available for callers that explicitly want a pointer" change) correctly rejects the conversion — but nothing intercepts the strided-BLAS dispatch before it gets there, so the products now throw.

Non-BLAS eltypes are no better off: view(Ai, 1:2, :)' * view(Bi, 1:2, :) with Int8 falls through to Base's generic matmul and dies with "Scalar indexing is disallowed" under allowscalar(false). So as of 0.3.2, strided views of JLArrays are effectively not multipliable at all.

Why this matters

JLArrays is the reference backend used downstream to emulate CUDA semantics in CPU CI. On real CUDA, view(A, 1:2, :)' * view(B, 1:2, :) works (CUBLAS supports strided device views), so the emulator now rejects code that is fine on the backend it emulates. Downstream example: JuliaGPU-style CI in cossio/RestrictedBoltzmannMachines.jl went red on the JLArrays 0.3.1 → 0.3.2 bump with unchanged code (fixed there by materializing the views: cossio/RestrictedBoltzmannMachines.jl#206).

To be clear, the 0.3.2 pointer guard itself looks like the right call — it exposed a real emulation gap that 0.3.1 was silently papering over with host BLAS.

Suggestion

Would it make sense for GPUArrays/JLArrays to provide LinearAlgebra.generic_matmatmul!/mul! coverage for strided SubArrays (and Adjoint/Transpose thereof) of AbstractGPUArray, routing them to the existing generic GPU matmul kernels, so wrapped views keep working and JLArray matches CuArray behavior? Alternatively, if erroring is the intended semantics for view products on JLArray, a targeted error ("matrix products with views of JLArrays are not supported; materialize with copy/getindex") would be much easier to act on than the Ptr guard firing deep inside BLAS.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions