JuliaGPU / JuliaGPU/GPUArrays.jl

Broadcasting on `SubArray` with inds of `Vector{Int}` fails with compiler issue

Open
#724 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Julia
Stars
450
Forks
104
Avg merge
1d 4h
Merged PRs (30d)
10

Description

MWE:

```julia
using CUDA, LinearAlgebra

A = CUDA.cuRAND.randn(64, 64)
B = CUDA.cuRAND.randn(32)

Ad = view(A, diagind(A))

view(Ad, [1, 3, 4, 16]) .= view(B, [2, 6, 8, 10])
```

Fails with:

```
ERROR: LoadError: GPU compilation of MethodInstance for (::GPUArrays.var"#gpu_broadcast_kernel_linear#_copyto!##1")(::KernelAbstractions.CompilerMetadata{KernelAbstractions.NDIteration.DynamicSize, KernelAbstractions.NDIteration.DynamicCheck, Nothing, CartesianIndices{1, Tuple{Base.OneTo{Int64}}}, KernelAbstractions.NDIteration.NDRange{1, KernelAbstractions.NDIteration.DynamicSize, KernelAbstractions.NDIteration.DynamicSize, CartesianIndices{1, Tuple{Base.OneTo{Int64}}}, CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}}, ::SubArray{Float32, 1, CuDeviceVector{Float32, 1}, Tuple{Vector{Int64}}, false}, ::Base.Broadcast.Broadcasted{CUDACore.CuArrayStyle{1, CUDACore.DeviceMemory}, Tuple{Base.OneTo{Int64}}, typeof(identity), Tuple{Base.Broadcast.Extruded{SubArray{Float32, 1, CuDeviceVector{Float32, 1}, Tuple{CuDeviceVector{Int64, 1}}, false}, Tuple{Bool}, Tuple{Int64}}}}) failed
KernelError: passing non-bitstype argument

Argument 3 to your kernel function is of type SubArray{Float32, 1, CUDACore.CuDeviceVector{Float32, 1}, Tuple{Vector{Int64}}, false}, which is not a bitstype:
.indices is of type Tuple{Vector{Int64}} which is not isbits.
.1 is of type Vector{Int64} which is not isbits.
.ref is of type MemoryRef{Int64} which is not isbits.
.mem is of type Memory{Int64} which is not isbits.

Only bitstypes, which are "plain data" types that are immutable
and contain no references to other values, can be used in GPU kernels.
For more information, see the `Base.isbitstype` function.

Stacktrace:
[1] check_invocation(job::GPUCompiler.CompilerJob)
@ GPUCompiler ~/.julia/packages/GPUCompiler/kLxLE/src/validation.jl:108
[2] compile_unhooked(output::Symbol, job::GPUCompiler.CompilerJob; kwargs::@Kwargs{})
@ GPUCompiler ~/.julia/packages/GPUCompiler/kLxLE/src/driver.jl:87
[3] compile_unhooked
@ ~/.julia/packages/GPUCompiler/kLxLE/src/driver.jl:80 [inlined]
[4] #compile#96
@ ~/.julia/packages/GPUCompiler/kLxLE/src/driver.jl:67 [inlined]
[5] compile(target::Symbol, job::GPUCompiler.CompilerJob)
@ GPUCompiler ~/.julia/packages/GPUCompiler/kLxLE/src/driver.jl:55
[6] #invoke_frozen#589
@ ~/.julia/dev/CUDA/CUDACore/src/initialization.jl:30 [inlined]
[7] invoke_frozen
@ ~/.julia/dev/CUDA/CUDACore/src/initialization.jl:26 [inlined]
[8] #compile##0
@ ~/.julia/dev/CUDA/CUDACore/src/compiler/compilation.jl:250 [inlined]
[9] JuliaContext(f::CUDACore.var"#compile##0#compile##1"{GPUCompiler.CompilerJob{GPUCompiler.PTXCompilerTarget, CUDACore.CUDACompilerParams}}; kwargs::@Kwargs{})
@ GPUCompiler ~/.julia/packages/GPUCompiler/kLxLE/src/driver.jl:34
[10] JuliaContext(f::Function)
@ GPUCompiler ~/.julia/packages/GPUCompiler/kLxLE/src/driver.jl:25
[11] compile(job::GPUCompiler.CompilerJob)
@ CUDACore ~/.julia/dev/CUDA/CUDACore/src/compiler/compilation.jl:249
[12] actual_compilation(cache::Dict{Any, CuFunction}, src::Core.MethodInstance, world::UInt64, cfg::GPUCompiler.CompilerConfig{GPUCompiler.PTXCompilerTarget, CUDACore.CUDACompilerParams}, compiler::typeof(CUDACore.compile), linker::typeof(CUDACore.link))
@ GPUCompiler ~/.julia/packages/GPUCompiler/kLxLE/src/execution.jl:245
[13] cached_compilation(cache::Dict{Any, CuFunction}, src::Core.MethodInstance, cfg::GPUCompiler.CompilerConfig{GPUCompiler.PTXCompilerTarget, CUDACore.CUDACompilerParams}, compiler::Function, linker::Function)
@ GPUCompiler ~/.julia/packages/GPUCompiler/kLxLE/src/execution.jl:159
[14] macro expansion
@ ~/.julia/dev/CUDA/CUDACore/src/compiler/execution.jl:450 [inlined]
[15] macro expansion
@ ./lock.jl:376 [inlined]
[16] cufunction(f::GPUArrays.var"#gpu_broadcast_kernel_linear#_copyto!##1", tt::Type{Tuple{KernelAbstractions.CompilerMetadata{KernelAbstractions.NDIteration.DynamicSize, KernelAbstractions.NDIteration.DynamicCheck, Nothing, CartesianIndices{1, Tuple{Base.OneTo{Int64}}}, KernelAbstractions.NDIteration.NDRange{1, KernelAbstractions.NDIteration.DynamicSize, KernelAbstractions.NDIteration.DynamicSize, CartesianIndices{1, Tuple{Base.OneTo{Int64}}}, CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}}, SubArray{Float32, 1, CuDeviceVector{Float32, 1}, Tuple{Vector{Int64}}, false}, Base.Broadcast.Broadcasted{CUDACore.CuArrayStyle{1, CUDACore.DeviceMemory}, Tuple{Base.OneTo{Int64}}, typeof(identity), Tuple{Base.Broadcast.Extruded{SubArray{Float32, 1, CuDeviceVector{Float32, 1}, Tuple{CuDeviceVector{Int64, 1}}, false}, Tuple{Bool}, Tuple{Int64}}}}}}; kwargs::@Kwargs{always_inline::Bool, maxthreads::Nothing})
@ CUDACore ~/.julia/dev/CUDA/CUDACore/src/compiler/execution.jl:445
[17] cufunction
@ ~/.julia/dev/CUDA/CUDACore/src/compiler/execution.jl:442 [inlined]
[18] #kernel_compile#737
@ ~/.julia/dev/CUDA/CUDACore/src/compiler/execution.jl:59 [inlined]
[19] macro expansion
@ ~/.julia/dev/CUDA/CUDACore/src/compiler/execution.jl:182 [inlined]
[20] (::KernelAbstractions.Kernel{CUDABackend, KernelAbstractions.NDIteration.DynamicSize, KernelAbstractions.NDIteration.DynamicSize, GPUArrays.var"#gpu_broadcast_kernel_linear#_copyto!##1"})(::SubArray{Float32, 1, CuArray{Float32, 1, CUDACore.DeviceMemory}, Tuple{Vector{Int64}}, false}, ::Vararg{Any}; ndrange::Tuple{Int64}, workgroupsize::Nothing)
@ CUDACore.CUDAKernels ~/.julia/dev/CUDA/CUDACore/src/CUDAKernels.jl:125
[21] Kernel
@ ~/.julia/dev/CUDA/CUDACore/src/CUDAKernels.jl:111 [inlined]
[22] _copyto!
@ ~/.julia/packages/GPUArrays/V2qKA/src/host/broadcast.jl:79 [inlined]
[23] materialize!
@ ~/.julia/packages/GPUArrays/V2qKA/src/host/broadcast.jl:43 [inlined]
[24] materialize!(dest::SubArray{Float32, 1, CuArray{Float32, 1, CUDACore.DeviceMemory}, Tuple{Vector{Int64}}, false}, bc::Base.Broadcast.Broadcasted{CUDACore.CuArrayStyle{1, CUDACore.DeviceMemory}, Nothing, typeof(identity), Tuple{SubArray{Float32, 1, CuArray{Float32, 1, CUDACore.DeviceMemory}, Tuple{CuArray{Int64, 1, CUDACore.DeviceMemory}}, false}}})
@ Base.Broadcast ./broadcast.jl:902
[25] top-level scope
@ ~/.julia/dev/CUDA/subarray_copy.jl:8
[26] include(mod::Module, _path::String)
@ Base ./Base.jl:306
[27] exec_options(opts::Base.JLOptions)
@ Base ./client.jl:317
[28] _start()
@ Base ./client.jl:550
in expression starting at /home/kshyatt/.julia/dev/CUDA/subarray_copy.jl:8
```

I'm posting this here rather than at `CUDA.jl` because I think this is more related to the existing bcast kernel. I understand these indices are not contiguous but this feels like it could be made to work?

Julia version 1.12.6
GPUArrays version 11.5.4
GPUCompiler version 1.13.0
CUDA 6.1.0

Contributor guide

No contributing guide indexed for this repository

Research direction

Reproduce the MWE with the listed Julia, GPUArrays, GPUCompiler, and CUDA versions, then inspect GPUArrays/src/host/broadcast.jl around _copyto! and gpu_broadcast_kernel_linear. Trace how the vector-indexed SubArray is passed to the GPU kernel. Done means the indexed broadcast assignment compiles and completes without the non-bitstype error while preserving the shown assignment semantics.

Written by the indexing model from the issue text.

Assessment

Tech stack
julia
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.