# Is it possibly to do atomic update on an array element?

**URL:** <https://discourse.julialang.org/t/is-it-possibly-to-do-atomic-update-on-an-array-element/112113>\
**Category:** General Usage\
**Created:** [March 26, 2024, 12:43am UTC](https://discourse.julialang.org/t/is-it-possibly-to-do-atomic-update-on-an-array-element/112113 "2024-03-26T00:43:07Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [March 26, 2024, 12:43am UTC](https://discourse.julialang.org/t/is-it-possibly-to-do-atomic-update-on-an-array-element/112113/1 "2024-03-26T00:43:07Z")

</div>

The manual seems to read “primitive type values only”.  
Also, just above that section is “API is deprecated”.

Does anyone has an insight into this?

---

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [March 26, 2024, 1:13am UTC](https://discourse.julialang.org/t/is-it-possibly-to-do-atomic-update-on-an-array-element/112113/2 "2024-03-26T01:13:20Z")

</div>

Is this a good way:

```julia
julia> avec = [Threads.Atomic{Int}(0) for _ in 1:5]
5-element Vector{Base.Threads.Atomic{Int64}}:
 Base.Threads.Atomic{Int64}(0)
 Base.Threads.Atomic{Int64}(0)
 Base.Threads.Atomic{Int64}(0)
 Base.Threads.Atomic{Int64}(0)
 Base.Threads.Atomic{Int64}(0)

julia> avec[4][] = 10
10

julia> avec
5-element Vector{Base.Threads.Atomic{Int64}}:
 Base.Threads.Atomic{Int64}(0)
 Base.Threads.Atomic{Int64}(0)
 Base.Threads.Atomic{Int64}(0)
 Base.Threads.Atomic{Int64}(10)
 Base.Threads.Atomic{Int64}(0)

```

and using `Atomic` type according to the ways detailed in the documentation: [Multi-Threading · The Julia Language](https://docs.julialang.org/en/v1/base/multi-threading/#Base.Threads.Atomic)

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [March 26, 2024, 1:19am UTC](https://discourse.julialang.org/t/is-it-possibly-to-do-atomic-update-on-an-array-element/112113/3 "2024-03-26T01:19:14Z")

</div>

That is one way, but it’s generally not going to be fast and it only works for a limited set of types. It’s also what’s eventually to be replaced by the new `@atomic` macros — but indeed I’m not sure how that’d work with an array.

Regardless, t’s often much better to use other constructs (like coarser-grained locks or channels) or more carefully segment your accesses and writes so you don’t have to deal with the overhead of synchronizing the state between cores.

---

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [March 26, 2024, 1:32am UTC](https://discourse.julialang.org/t/is-it-possibly-to-do-atomic-update-on-an-array-element/112113/4 "2024-03-26T01:32:32Z")

</div>

An unclean way would be to add a lock to the special type in the array. Something like:

```julia
mutable struct NewAtomicMutable
    lck::ReentrantLock
    a::Int
    b::Int
end

cvec = [NewAtomicMutable(Base.ReentrantLock(), 0, 0) for _ in 1:5]

for i in 1:10
    idx = rand(eachindex(cvec))
    lock(cvec[idx].lck)
    try
        cvec[idx].a += 1
        cvec[idx].b += 2
    finally
        unlock(cvec[idx].lck)
    end
end

```

The last loop atomically modifies the data fields of the mutable struct.  
This is not very clean, and can be abstracted to a new Array type. Perhaps someone knows about an existing implementation (sounds like a construct which would in occasional use).

Actually, for strictly update operations, a SpinLock might be more performant:

```julia
mutable struct NewAtomicSpin
    lck::Base.Threads.SpinLock
    a::Int
    b::Int
end

cvec = [NewAtomicSpin(Base.Threads.SpinLock(), 0, 0) for _ in 1:5]

```

(can be used with the same update loop)

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [March 26, 2024, 1:32am UTC](https://discourse.julialang.org/t/is-it-possibly-to-do-atomic-update-on-an-array-element/112113/5 "2024-03-26T01:32:57Z")

</div>

When will the new macro land, do you think?

Btw: I’ve seen papers that claim atomics can work well in C++ (2011) programs.  
It might be worthwhile to check that out.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [March 26, 2024, 1:45am UTC](https://discourse.julialang.org/t/is-it-possibly-to-do-atomic-update-on-an-array-element/112113/6 "2024-03-26T01:45:35Z")

</div>

Note that as of Julia 1.11, there is an actually right way of doing this which is `AtomicMemory`.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [March 26, 2024, 1:49am UTC](https://discourse.julialang.org/t/is-it-possibly-to-do-atomic-update-on-an-array-element/112113/7 "2024-03-26T01:49:02Z")

</div>

The new APIs are already here, since v1.7: [Multi-Threading · The Julia Language](https://docs.julialang.org/en/v1/base/multi-threading/#Atomic-operations). That’s why the stuff below it is marked as deprecated.

~~I believe the new way to work with array elements isn’t quite user-friendly and documented yet — it’s the “primitive” and unsafe pointer operations towards the end of that section~~ (edit: see Oscars post above). I’ve not tried the new APIs yet.

---

<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:** [March 26, 2024, 2:02am UTC](https://discourse.julialang.org/t/is-it-possibly-to-do-atomic-update-on-an-array-element/112113/8 "2024-03-26T02:02:48Z")

</div>

Before 1.11 there is Atomix.jl

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [March 26, 2024, 1:11pm UTC](https://discourse.julialang.org/t/is-it-possibly-to-do-atomic-update-on-an-array-element/112113/9 "2024-03-26T13:11:41Z")

</div>

I wonder how expensive (memory-wise) that would be?

---

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [March 26, 2024, 1:32pm UTC](https://discourse.julialang.org/t/is-it-possibly-to-do-atomic-update-on-an-array-element/112113/10 "2024-03-26T13:32:14Z")

</div>

Correctness has a price, and if the integrity of the data-structure making array elements is at stake, it’s worth paying it. This connects to a lot of discussion of row-based locking vs table locks in DBs and key-value stores.

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [March 26, 2024, 1:33pm UTC](https://discourse.julialang.org/t/is-it-possibly-to-do-atomic-update-on-an-array-element/112113/11 "2024-03-26T13:33:19Z")

</div>

This is for _very_ large arrays, though. Easily over a billion elements.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [March 26, 2024, 1:46pm UTC](https://discourse.julialang.org/t/is-it-possibly-to-do-atomic-update-on-an-array-element/112113/12 "2024-03-26T13:46:27Z")

</div>

In that case, you might want to partition the array into chunks and have locks over those chunks. Having a lock per element will be really expensive.

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [March 26, 2024, 1:49pm UTC](https://discourse.julialang.org/t/is-it-possibly-to-do-atomic-update-on-an-array-element/112113/13 "2024-03-26T13:49:43Z")

</div>

There is a paper ([On Memory Traffic and Optimisations for Low-order Finite Element Assembly Algorithms on Multi-core CPUs | ACM Transactions on Mathematical Software](https://doi.org/10.1145/3503925)) which claims good scalability with OpenMP using atomic access to array elements. Intriguing…

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [March 26, 2024, 1:56pm UTC](https://discourse.julialang.org/t/is-it-possibly-to-do-atomic-update-on-an-array-element/112113/14 "2024-03-26T13:56:46Z")

</div>

If your eltype has support for native atomic operations then it will be pretty free (locks are at least a word, but atomic fields are free for supported types). It sounds like 1.11 `AtomicMemory` or Atomix.jl is what you want then.

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [March 26, 2024, 3:28pm UTC](https://discourse.julialang.org/t/is-it-possibly-to-do-atomic-update-on-an-array-element/112113/15 "2024-03-26T15:28:40Z")

</div>

FWIW, there is a small wrinkle with `Vector` before the big `Memory` change – you can memory corrupt if a different thread `reallocs` the thing via resizing.

Almost surely not a problem for your intended use, but probably the reason why this wasn’t always a part of the official API (this was unfixable with the old layout).
