# Adding at specific CuArray position

**URL:** <https://discourse.julialang.org/t/adding-at-specific-cuarray-position/113855>\
**Category:** GPU\
**Tags:** question\
**Created:** [May 5, 2024, 8:39am UTC](https://discourse.julialang.org/t/adding-at-specific-cuarray-position/113855 "2024-05-05T08:39:16Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Andrea\_Deflorio](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andrea_deflorio/32/34365_2.png) [@Andrea\_Deflorio](https://discourse.julialang.org/u/Andrea_Deflorio)\
**Post date:** [May 5, 2024, 8:39am UTC](https://discourse.julialang.org/t/adding-at-specific-cuarray-position/113855/1 "2024-05-05T08:39:16Z")

</div>

How to fix this function?  
Also how to fix the line #@atomic counts[indices[idx]] += 1, it doesn’t compile at all.

```julia
function count_indices(indices::CuArray{Int64,1}, maxSize::Int64)
    # Initialize a CuArray of zeros with size maxSize
    counts = CUDA.zeros(Int64, maxSize)

    # Define the kernel function
    function kernel(indices, counts)
        idx = (blockIdx().x - 1) * blockDim().x + threadIdx().x
        if idx <= length(indices)
            #@atomic counts[indices[idx]] += 1
            CUDA.atomic_add!(counts, indices[idx], 1)
        end
        return
    end

    # Launch the kernel
    threads = 256
    blocks = cld(length(indices), threads)
    @cuda threads=threads blocks=blocks kernel(indices, counts)

    return counts
end

count_indices(CuArray([1, 2, 3, 1, 3, 3, 3, 1, 1, 1, 1]), 4)

```

This is the error I get in julia v1.9.1:  
ERROR: InvalidIRError: compiling MethodInstance for (::var"#kernel#7")(::CuDeviceVector{Int64, 1}, ::CuDeviceVector{Int64, 1}) resulted in invalid LLVM IR  
Reason: unsupported dynamic function invocation (call to atomic\_add!)

---

<div class="post-metadata">

**Author:** ![Ahmed\_Salih](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ahmed_salih/32/206579_2.png) [@Ahmed\_Salih](https://discourse.julialang.org/u/Ahmed_Salih)\
**Post date:** [May 5, 2024, 9:05am UTC](https://discourse.julialang.org/t/adding-at-specific-cuarray-position/113855/2 "2024-05-05T09:05:26Z")

</div>

I haven’t thought too much about what you want to do, but the way to use `@atomic` is as shown here:

```julia
function count_indices(indices::CuArray{Int64,1}, maxSize::Int64)
    # Initialize a CuArray of zeros with size maxSize
    counts = CUDA.zeros(Int64, maxSize)

    # Define the kernel function
    function kernel(indices, counts)
        idx = (blockIdx().x - 1) * blockDim().x + threadIdx().x
        if idx <= length(indices)
            CUDA.@atomic counts[indices[idx]] += 1
        end
        return
    end

    # Launch the kernel
    threads = 256
    blocks = cld(length(indices), threads)
    @cuda threads=threads blocks=blocks kernel(indices, counts)

    return counts
end

count_indices(CuArray([1, 2, 3, 1, 3, 3, 3, 1, 1, 1, 1]), 4)

```

With result:

```julia
julia> count_indices(CuArray([1, 2, 3, 1, 3, 3, 3, 1, 1, 1, 1]), 4)
4-element CuArray{Int64, 1, CUDA.Mem.DeviceBuffer}:
 6
 1
 4
 0

```

Some tips;

1. Use `CuVector` instead of `CuArray`
2. Use `Int` instead of specifying specifically `IntXX`
3. If you are going to call this function a lot, preallocate `count` outside and make a in-place function, `count_indices!`. Then you can always define the function to do everything at once again

Kind regards

---

<div class="post-metadata">

**Author:** ![Andrea\_Deflorio](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andrea_deflorio/32/34365_2.png) [@Andrea\_Deflorio](https://discourse.julialang.org/u/Andrea_Deflorio)\
**Post date:** [May 5, 2024, 11:23am UTC](https://discourse.julialang.org/t/adding-at-specific-cuarray-position/113855/3 "2024-05-05T11:23:39Z")

</div>

It works fine, Thank you!

---

<div class="post-metadata">

**Author:** ![maleadt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maleadt/32/10097_2.png) [@maleadt](https://discourse.julialang.org/u/maleadt)\
**Post date:** [May 5, 2024, 5:54pm UTC](https://discourse.julialang.org/t/adding-at-specific-cuarray-position/113855/4 "2024-05-05T17:54:51Z")

</div>

> [@Andrea\_Deflorio](#):
>
> Reason: unsupported dynamic function invocation (call to atomic\_add!)

FWIW, the underlying issue was probably that `atomic_add!` (and all other low-level atomic intrinsics) are really strict wrt. which types of arguments they accept, while `CUDA.@atomic` performs automatic conversions.

---

<div class="post-metadata">

**Author:** ![Ahmed\_Salih](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ahmed_salih/32/206579_2.png) [@Ahmed\_Salih](https://discourse.julialang.org/u/Ahmed_Salih)\
**Post date:** [May 6, 2024, 12:46pm UTC](https://discourse.julialang.org/t/adding-at-specific-cuarray-position/113855/5 "2024-05-06T12:46:31Z")

</div>

Is the a way to get `CUDA.@atomic` add to work if the underlying values are `SVector`?

I have not had success with that.

---

<div class="post-metadata">

**Author:** ![SteffenPL](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/steffenpl/32/206270_2.png) [@SteffenPL](https://discourse.julialang.org/u/SteffenPL)\
**Post date:** [May 6, 2024, 1:34pm UTC](https://discourse.julialang.org/t/adding-at-specific-cuarray-position/113855/6 "2024-05-06T13:34:02Z")

</div>

I was also doing the same today. Seems like GPUs in general cannot atomically add to multiple values at once.

If you have a vector of `SVector`s, you can use `reshape(reinterpret(Float32, X), 3, length(X))` to get a suitable vector for componentwise atomic actions.

---

<div class="post-metadata">

**Author:** ![Ahmed\_Salih](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ahmed_salih/32/206579_2.png) [@Ahmed\_Salih](https://discourse.julialang.org/u/Ahmed_Salih)\
**Post date:** [May 6, 2024, 1:58pm UTC](https://discourse.julialang.org/t/adding-at-specific-cuarray-position/113855/7 "2024-05-06T13:58:25Z")

</div>

Thanks! That kind of removes the perk of using `SVector` though, but a possible work around yes
