How to pass a mutable struct to CUDA kernel argument

Hi all! I’m exploring ways to pass a mutable struct as an argument to a CUDA kernel. For example,

# Define a custom struct here
mutable struct MyStruct
    field1::Float32
    field2::Float32
    field3::Float32
    ...
end

# Pass the custom struct as argument of a kernel
function MyKernel!(arg1, arg2, arg3, arg4::MyStruct)
    # Use arg4 to do something
    return nothing
end

The mutable struct always gave errors like passing and using non-bitstype argument. But if the struct is defined as immutable, the CUDA kernel can run successfully. My problem is that I really have to make this struct mutable for other purposes, so is there any way to make it work?

Also, I tried the Adapt package and the example from here Using custom structs · CUDA.jl, but unfortunately I found that this example did not work for mutable struct Interpolate{A}. It caused the same errors like passing and using non-bitstype argument. Hope someone can provide suggestions on how to handle mutable structures within CUDA kernels. Thanks a lot!

Mutable structs are unsupported. You can use an array of immutable structs, and replace elements. Packages like Setfield.jl/Accessors.jl make this easier.

What I do is in my functions that run a CUDA kernel, I have a gate if statement that checks if I’ll run CUDA or CPU. If CUDA, then I take the members of the structs that I need and put them into a named tuple. Like the struct bodies that contains centers, areas, etc:

bodiesGPU = (centers=CuArray(bodies.centers),areas=CuArray(bodies.areas))

Then you can use common functions for CPU and GPU, as named tuples and structs behave pretty much the same way. You just change how the functions are called (if CUDA, call using bodiesGPU, else bodies).

1 Like

Thank you all! I will try as you have suggested.