# Re the blog post: PSA: Thread-local state is no longer recommended

**URL:** https://discourse.julialang.org/t/re-the-blog-post-psa-thread-local-state-is-no-longer-recommended/101303
**Category:** Internals & Design
**Created:** [July 7, 2023, 9:25am UTC](https://discourse.julialang.org/t/re-the-blog-post-psa-thread-local-state-is-no-longer-recommended/101303 "2023-07-07T09:25:11Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![wherrera](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wherrera/32/5288_2.png) [@wherrera](https://discourse.julialang.org/u/wherrera)
#### Post date: [July 7, 2023, 9:25am UTC](https://discourse.julialang.org/t/re-the-blog-post-psa-thread-local-state-is-no-longer-recommended/101303/1 "2023-07-07T09:25:11Z")

</div>

Disfavored in the blog post, due to issues with threadid, was:

```
using Base.Threads: nthreads, @threads, threadid

states = [some_initial_value for _ in 1:nthreads()]
@threads for x in some_data
    tid = threadid()
    old_val = states[tid]
    new_val = some_operator(old_val, f(x))
    states[tid] = new_val 
end     
do_something(states)

```

Proposed solution: **enumerate** the loop with the index as a program-specific task id:

```
using Base.Threads: @threads

states = [some_initial_value for _ in eachindex(x)] # <-- changed
@threads for (id, x) in enumerate(some_data) # <-- the key change is here
    old_val = states[id]
    new_val = some_operator(old_val, f(x))
    states[id] = new_val
end
do_something(states)

```

---

<div class="post-metadata">

### Author: ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)
#### Post date: [July 7, 2023, 9:33am UTC](https://discourse.julialang.org/t/re-the-blog-post-psa-thread-local-state-is-no-longer-recommended/101303/2 "2023-07-07T09:33:18Z")

</div>

Isn’t that pretty much the same pattern as [the one proposed in the other thread](https://discourse.julialang.org/t/psa-thread-local-state-is-no-longer-recommended-common-misconceptions-about-threadid-and-nthreads/101274/8) (the latter just being more explicit/verbose)?

> [@wherrera](#):
>
> `states = [some_initial_value for _ in eachindex(x)] # <-- changed`

`x` isn’t defined here?

---

<div class="post-metadata">

### Author: ![wherrera](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wherrera/32/5288_2.png) [@wherrera](https://discourse.julialang.org/u/wherrera)
#### Post date: [July 7, 2023, 9:50am UTC](https://discourse.julialang.org/t/re-the-blog-post-psa-thread-local-state-is-no-longer-recommended/101303/3 "2023-07-07T09:50:40Z")

</div>

Sorry, that could have been some\_data, and I was not posting working code (the example I was quoting did not define some\_data)… I will add below:

```
const some_data = [3, 4, 5]
states = [some_initial_value for _ in eachindex(some_data)] # <-- changed
@Threads.threads for (id, x) in enumerate(some_data) # <-- the key change is here
    old_val = states[id]
    new_val = some_operator(old_val, f(x))
    states[id] = new_val
end
do_something(states)

```

---

<div class="post-metadata">

### Author: ![jakobnissen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jakobnissen/32/13477_2.png) [@jakobnissen](https://discourse.julialang.org/u/jakobnissen)
#### Post date: [July 7, 2023, 10:10am UTC](https://discourse.julialang.org/t/re-the-blog-post-psa-thread-local-state-is-no-longer-recommended/101303/4 "2023-07-07T10:10:33Z")

</div>

I use this pattern myself. As written, it doesn’t actually work though.

```julia
julia> result = zeros(10)
       Threads.@threads for (i, x) in enumerate(19:28)
           result[i] = x ÷ 2
       end
ERROR: TaskFailedException

    nested task error: MethodError: no method matching firstindex(::Base.Iterators.Enumerate{UnitRange{Int64}})

```

You need to do `collect(enumerate(some_data))`. I wish the implementation didn’t require this, but a single collect over a multithreaded loop is usually insignificant.

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [July 7, 2023, 10:12am UTC](https://discourse.julialang.org/t/re-the-blog-post-psa-thread-local-state-is-no-longer-recommended/101303/5 "2023-07-07T10:12:45Z")

</div>

Unfortunately, the `collect` version is not always correct, e.g. for channels.

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [July 7, 2023, 11:47am UTC](https://discourse.julialang.org/t/re-the-blog-post-psa-thread-local-state-is-no-longer-recommended/101303/6 "2023-07-07T11:47:22Z")

</div>

> [@wherrera](#):
>
> `@threads for (id, x) in enumerate(some_data)`

That is ok, but then you need the number of states to be the same as the number of elements in the `some_data` array.

More generally one wants a buffer of length `nthreads`, which is independent of the number of tasks. That is why in general the proposal is to partition the workload in chunks and then use the chunk index (instead of `threadid()`).

---

<div class="post-metadata">

### Author: ![tecosaur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tecosaur/32/23206_2.png) [@tecosaur](https://discourse.julialang.org/u/tecosaur)
#### Post date: [July 8, 2023, 5:31am UTC](https://discourse.julialang.org/t/re-the-blog-post-psa-thread-local-state-is-no-longer-recommended/101303/7 "2023-07-08T05:31:06Z")

</div>

Sometimes the `collect` for is also very expensive, in terms of allocation/compute. Is there much of a chance of this requirement being removed in the future?

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [July 8, 2023, 8:55am UTC](https://discourse.julialang.org/t/re-the-blog-post-psa-thread-local-state-is-no-longer-recommended/101303/8 "2023-07-08T08:55:27Z")

</div>

I think you can use `pairs` there, and you don’t need the collection. But you could also use `eachindex` just indexing the elements inside the loop.
