# Why Atomix.@atomic b\[\] += a\[i\] works and b\[\] = b\[\] + a\[i\] does not

**URL:** <https://discourse.julialang.org/t/why-atomix-atomic-b-a-i-works-and-b-b-a-i-does-not/134627>\
**Category:** GPU\
**Created:** [December 18, 2025, 9:10am UTC](https://discourse.julialang.org/t/why-atomix-atomic-b-a-i-works-and-b-b-a-i-does-not/134627 "2025-12-18T09:10:19Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tomas\_Pevny](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomas_pevny/32/25466_2.png) [@Tomas\_Pevny](https://discourse.julialang.org/u/Tomas_Pevny)\
**Post date:** [December 18, 2025, 9:10am UTC](https://discourse.julialang.org/t/why-atomix-atomic-b-a-i-works-and-b-b-a-i-does-not/134627/1 "2025-12-18T09:10:19Z")

</div>

Hi all,

I am updating my lecture on GPU programming and this year, I would like to have kernels written in CUDA.jl and KernelAbstractions.jl side by side. The idea is to show students, how GPU accelerators are similar and that with Julia ecosystem, they can write pretty general stuff.

I am working on a classic example of reduction, which @maleadt uses in his talks. But I have encoutered a weird behavior

Specifically this kernel works

```julia
using Metal, BenchmarkTools
using KernelAbstractions
import KernelAbstractions as KA
using Atomix

@kernel function reduce_atomic(op, a, b)
    i = @index(Global)
    Atomix.@atomic b[] += a[i]
end

x = rand(Float32, 1024, 1024);
cx = MtlArray(x);
backend = KA.get_backend(cx);
cb = MtlArray([0f0]);
reduce_atomic(backend, 64)(+, cx, cb, ndrange=size(cx))
Metal.GPUArraysCore.@allowscalar cb[]
sum(x)

```

while this does not

```julia

@kernel function reduce_atomic(op, a, b)
    i = @index(Global)
    Atomix.@atomic b[] = b[] + a[i]
end

x = rand(Float32, 1024, 1024);
cx = MtlArray(x);
backend = KA.get_backend(cx);
cb = MtlArray([0f0]);
reduce_atomic(backend, 64)(+, cx, cb, ndrange=size(cx))
Metal.GPUArraysCore.@allowscalar cb[]
sum(x)

```

Can anyone please help me to understand, what is going on?

---

<div class="post-metadata">

**Author:** ![vchuravy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vchuravy/32/8_2.png) [@vchuravy](https://discourse.julialang.org/u/vchuravy)\
**Post date:** [December 18, 2025, 9:12am UTC](https://discourse.julialang.org/t/why-atomix-atomic-b-a-i-works-and-b-b-a-i-does-not/134627/2 "2025-12-18T09:12:57Z")

</div>

The `@atomic` macro does a syntax analysis only on the operator separating the left hand from the right hand side.

So it’s semantically different to do `+=` which we will turn into an atomic increment, and `=` which is just an atomic assignment.

The rhs expression will be evaluated independently.

---

<div class="post-metadata">

**Author:** ![Tomas\_Pevny](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomas_pevny/32/25466_2.png) [@Tomas\_Pevny](https://discourse.julialang.org/u/Tomas_Pevny)\
**Post date:** [December 18, 2025, 9:20am UTC](https://discourse.julialang.org/t/why-atomix-atomic-b-a-i-works-and-b-b-a-i-does-not/134627/3 "2025-12-18T09:20:40Z")

</div>

That makes a lot of sense. Can you recommend please, how to write it correctly?

---

<div class="post-metadata">

**Author:** ![vchuravy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vchuravy/32/8_2.png) [@vchuravy](https://discourse.julialang.org/u/vchuravy)\
**Post date:** [December 18, 2025, 9:35am UTC](https://discourse.julialang.org/t/why-atomix-atomic-b-a-i-works-and-b-b-a-i-does-not/134627/4 "2025-12-18T09:35:05Z")

</div>

```julia-auto
@kernel function reduce_atomic(op, a, b)
    i = @index(Global)
    Atomix.@atomic b[] += a[i]
end

```

This is correct, no?

Perhaps the confusion is that `CUDA.@atomic` is different from `Atomix.@atomic` and IIRC the CUDA version might support the other variant as well, but that is not portable.

---

<div class="post-metadata">

**Author:** ![Tomas\_Pevny](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomas_pevny/32/25466_2.png) [@Tomas\_Pevny](https://discourse.julialang.org/u/Tomas_Pevny)\
**Post date:** [December 18, 2025, 9:44am UTC](https://discourse.julialang.org/t/why-atomix-atomic-b-a-i-works-and-b-b-a-i-does-not/134627/5 "2025-12-18T09:44:58Z")

</div>

This is correct, but it does uses `op`. What if `op = max` ?

I would be fine to know that `CUDA.@atomic` is more general and `Atomix.@atomic` supports only subset, but in a portable way. I just do not want to rule out a possible solution.

Thanks a lot for help!

---

<div class="post-metadata">

**Author:** ![vchuravy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vchuravy/32/8_2.png) [@vchuravy](https://discourse.julialang.org/u/vchuravy)\
**Post date:** [December 18, 2025, 10:02am UTC](https://discourse.julialang.org/t/why-atomix-atomic-b-a-i-works-and-b-b-a-i-does-not/134627/6 "2025-12-18T10:02:23Z")

</div>

It’s less that `CUDA.@atomic` is more general. It was implemented first, then we added Atomix to support CPU and other backends, and the Atomix design ended up influencing `Base. @atomic`

> **[Base.@atomic - Multi-Threading · The Julia Language](https://docs.julialang.org/en/v1/base/multi-threading/#Base.%40atomic)**
>
> Mark var or ex as being performed atomically, if ex is a supported expression. If no order is specified it defaults to :sequentially\_consistent. | Documentation for The Julia Language.

So the general syntax should actually be

```julia-auto
@kernel function reduce_atomic(op, a, b)
    i = @index(Global)
    Atomix.@atomic b[] op a[i]
end

```

But I am unsure if that is generally supported by all backends currently

---

<div class="post-metadata">

**Author:** ![Tomas\_Pevny](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomas_pevny/32/25466_2.png) [@Tomas\_Pevny](https://discourse.julialang.org/u/Tomas_Pevny)\
**Post date:** [December 18, 2025, 10:48am UTC](https://discourse.julialang.org/t/why-atomix-atomic-b-a-i-works-and-b-b-a-i-does-not/134627/7 "2025-12-18T10:48:02Z")

</div>

thanks a lot. I undersand
