# Passing custom struct into kernel function

**URL:** <https://discourse.julialang.org/t/passing-custom-struct-into-kernel-function/94069>\
**Category:** GPU\
**Created:** [February 4, 2023, 10:27pm UTC](https://discourse.julialang.org/t/passing-custom-struct-into-kernel-function/94069 "2023-02-04T22:27:04Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![FujiwaraTakumiEH](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fujiwaratakumieh/32/37975_2.png) [@FujiwaraTakumiEH](https://discourse.julialang.org/u/FujiwaraTakumiEH)\
**Post date:** [February 4, 2023, 10:27pm UTC](https://discourse.julialang.org/t/passing-custom-struct-into-kernel-function/94069/1 "2023-02-04T22:27:04Z")

</div>

Hello,

I’m still a little confused about `Adapt.jl`. I read several posts in the forum and tried it for my case, but it did not work…😂

I have a custom struct like this:

```julia
using Adapt
using CUDA

# T is either Float64 or Float32
mutable struct MyStruct{T}
    a::T
    b::AbstractArray{T, 1}
    c::AbstractArray{T, 2}
end

struct GPUHelper{T}
    a::T
    b::CuDeviceVector{T, 1}
    c::CuDeviceMatrix{T, 1}
end

Adapt.adapt_structure(to, MS::MyStruct) = GPUHelper(
              MS.a ,
    adapt(to, MS.b),
    adapt(to, MS.c)
)

```

My aim is to pass `data_cpu` into GPU (`data_gpu`) and use it in a kernel function, so I did:

```julia
a = 3.8
b = rand(10)
c = rand(10, 2)
data_cpu = MyStruct{Float64}(a, b, c)
data_gpu = MyStruct{Float64}(a, CuArray(b), CuArray(c))

isbits(cudaconvert(data_gpu)) # true

function gpu!(data_gpu)
    # kernel function
    return nothing
end

```

and then, I need to copy the `data_gpu` back to `data_cpu` by using `Adapt.jl`.

The above code works, but I have the following questions:

1. In my case, fields `.b` and `.c` are always `Vector{T}` and `Array{Float64, 2}`, however, it seems I cannot change their types like this.
2. As you can see how I get `data_gpu`. Considering the number of fields, this writing style may not be very pretty. I guess I should be able to implement it with something like `data_gpu = adapt(CuArray, data_cpu)` or `data_cpu = adapt(Array, data_gpu)`, but unfortunately I get the following error:

```julia
ERROR: MethodError: no method matching GPUHelper(::Float64, ::CuArray{Float64, 1, CUDA.Mem.DeviceBuffer}, ::CuArray{Float64, 2, CUDA.Mem.DeviceBuffer})
Closest candidates are:
  GPUHelper(::T, ::CuDeviceVector{T, 1}, ::CuDeviceMatrix{T, 1}) where T at c:\test\case.jl:11
Stacktrace:
 [1] adapt_structure(to::Type, MS::MyStruct{Float64})
   @ Main c:\test\case.jl:16
 [2] adapt(to::Type, x::MyStruct{Float64})
   @ Adapt C:\Users\test\.julia\packages\Adapt\0zP2x\src\Adapt.jl:40
 [3] top-level scope
   @ REPL[1]:1

```

Thank you so much~

---

<div class="post-metadata">

**Author:** ![ToucheSir](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/touchesir/32/14411_2.png) [@ToucheSir](https://discourse.julialang.org/u/ToucheSir)\
**Post date:** [February 4, 2023, 10:43pm UTC](https://discourse.julialang.org/t/passing-custom-struct-into-kernel-function/94069/2 "2023-02-04T22:43:19Z")

</div>

> [@FujiwaraTakumiEH](#):
>
> ```julia
> struct GPUHelper{T}
> a::T
> b::CuDeviceVector{T, 1}
> c::CuDeviceMatrix{T, 1}
> end
> 
> ```

You can make the types of `b` and `c` parametric so that they support both host-side `CuArray`s and device-side `CuDeviceArray`s.

```julia
struct GPUHelper{T, B<:AbstractVector{T}, C<:AbstractMatrix{T}}
    a::T
    b::B
    c::C
end

```
