Use of static array in a kernel function

Can I use StaticArrays in a kernel function? I wanted to use registers allocated for each thread. I thought that SVector would do that for me so I tried the following simple function. But, it says the kernel is returning Union{}. I do not understand why the body of the code is supposed to return Union{}.

julia> using CUDA

julia> using StaticArrays

julia> function register()
       x = SVector{3,Float64}
       x[1] = 1.0
       return nothing
       end
register (generic function with 1 method)

julia> @device_code_warntype @cuda threads=64 blocks=1 register()
PTX CompilerJob of kernel register() for sm_70

Variables
  #self#::Core.Compiler.Const(register, false)
  x::Type{SArray{Tuple{3},Float64,1,3}}

Body::Union{}
1 ─     (x = Core.apply_type(Main.SVector, 3, Main.Float64))
│       Base.setindex!(x::Core.Compiler.Const(SArray{Tuple{3},Float64,1,3}, false), 1.0, 1)
└──     Core.Compiler.Const(:(return Main.nothing), false)
ERROR: GPU compilation of kernel register() failed
KernelError: kernel returns a value of type `Union{}`

Make sure your kernel function ends in `return`, `return nothing` or `nothing`.
If the returned value is of type `Union{}`, your Julia code probably throws an exception.
Inspect the code with `@device_code_warntype` for more details.

You definitely can, StaticArrays are super handy in kernels since they don’t allocate (which is a requirement of kernel code). The problem with your code above is just that its not valid CPU code either, your x variable is just a type, not an instance of an SVector. Here’s a similar example that works,

using StaticArrays, Setfield

function register()
    x = @SVector Float64[0, 0, 0]
    @set! x[1] = 1
    return nothing
end

Note also the use of @set! from Setfield since you can’t actually mutate the SVector. Depending on what you’re trying to do, that could be useful (though not necessarily the most performant thing).

3 Likes