# Multithreaded for loops in Julia

**URL:** https://discourse.julialang.org/t/multithreaded-for-loops-in-julia/130728
**Category:** Julia at Scale
**Tags:** question
**Created:** [July 15, 2025, 5:14am UTC](https://discourse.julialang.org/t/multithreaded-for-loops-in-julia/130728 "2025-07-15T05:14:31Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![random\_guy](https://avatars.discourse-cdn.com/v4/letter/r/e0b2c6/32.png) [@random\_guy](https://discourse.julialang.org/u/random_guy)
#### Post date: [July 15, 2025, 5:14am UTC](https://discourse.julialang.org/t/multithreaded-for-loops-in-julia/130728/1 "2025-07-15T05:14:31Z")

</div>

Hello everyone,

I am a bit new to multithreading and I would like to know what the best way to multithread a for loop is. The unthreaded for loop is the following, where I’ve included in-place matrix modification and the calculation of a scalar quantity as a simplified version of my intended use case:

Unthreaded code:

```julia
ans = 0.0
@inbounds for i in 1:M
    @simd for j in 1:N 
        A[i, j] = f(i, j)
        ans += g(A[i, j])
    end
end

```

Here’s an approach with a buffer managed using threadid(). This is kind of what chatGPT suggested.

```julia
buffer = zeros(nthreads())

@threads for i in 1:M
    tid = threadid()
    local_accumulator = 0.0
    @inbounds begin 
        @simd for j in 1:N 
            A[i, j] = f(i, j)
            local_accumulator += g(A[i, j])
        end
        buffer[tid] += local_accumulator 
    end
end
ans = sum(buffer)

```

And here’s an approach based on reading the Julia documentation.

```julia
nt = nthreads()
chunks = Iterators.partition(1:M, div(M, nt))
tasks = map(chunks) do chunk 
    @spawn begin 
        chunk_sum = 0.0
        @inbounds begin 
            for i in chunk 
                @simd for j in 1:N 
                    A[i, j] = f(i, j)
                    chunk_sum += g(A[i, j])
                end                
            end
        end
        chunk_sum
    end
end
chunk_sums = fetch.(tasks)
ans = sum(chunk_sums)

```

I guess my question is, which approach for multithreading is better? Which is always guaranteed to work? Thank you!

---

<div class="post-metadata">

### Author: ![yolhan\_mannes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yolhan_mannes/32/220485_2.png) [@yolhan\_mannes](https://discourse.julialang.org/u/yolhan_mannes)
#### Post date: [July 15, 2025, 6:02am UTC](https://discourse.julialang.org/t/multithreaded-for-loops-in-julia/130728/2 "2025-07-15T06:02:41Z")

</div>

The first one may be bad you need to do `@threads :static for...` when you have a buffer like that to make sure it always works (it will freeze the threadid to always refer to the same thread on you machine). It’s in the doc somewhere [Multi-Threading · The Julia Language](https://docs.julialang.org/en/v1/manual/multi-threading/). For the second one I think it’s fine but there may be better ways. Also since most of the work you want parelel on is in the inner loop you could remove the buffer and make an atomic operation at the end instead in this case no need for `:static`.  
As always benchmarking is your friend

---

<div class="post-metadata">

### Author: ![random\_guy](https://avatars.discourse-cdn.com/v4/letter/r/e0b2c6/32.png) [@random\_guy](https://discourse.julialang.org/u/random_guy)
#### Post date: [July 15, 2025, 6:22am UTC](https://discourse.julialang.org/t/multithreaded-for-loops-in-julia/130728/3 "2025-07-15T06:22:49Z")

</div>

Thank you!

---

<div class="post-metadata">

### Author: ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)
#### Post date: [July 15, 2025, 6:50am UTC](https://discourse.julialang.org/t/multithreaded-for-loops-in-julia/130728/4 "2025-07-15T06:50:36Z")

</div>

See also:

- [PSA: Thread-local state is no longer recommended](https://julialang.org/blog/2023/07/PSA-dont-use-threadid/)
- [GitHub - JuliaFolds2/OhMyThreads.jl: Simple multithreading in julia](https://github.com/JuliaFolds2/OhMyThreads.jl)

---

<div class="post-metadata">

### Author: ![random\_guy](https://avatars.discourse-cdn.com/v4/letter/r/e0b2c6/32.png) [@random\_guy](https://discourse.julialang.org/u/random_guy)
#### Post date: [July 15, 2025, 7:06am UTC](https://discourse.julialang.org/t/multithreaded-for-loops-in-julia/130728/5 "2025-07-15T07:06:31Z")

</div>

Thank you! From what I understand, it’s just not recommended to use the @threads macro?

---

<div class="post-metadata">

### Author: ![yolhan\_mannes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yolhan_mannes/32/220485_2.png) [@yolhan\_mannes](https://discourse.julialang.org/u/yolhan_mannes)
#### Post date: [July 15, 2025, 7:09am UTC](https://discourse.julialang.org/t/multithreaded-for-loops-in-julia/130728/6 "2025-07-15T07:09:59Z")

</div>

It’s not recommended to rely on threadid that’s all 😉 obviously it’s always better to use OhMyThreads.jl or ThreadsX.jl but it doesn’t mean it’s not recommended to do otherwise

---

<div class="post-metadata">

### Author: ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)
#### Post date: [July 15, 2025, 8:20am UTC](https://discourse.julialang.org/t/multithreaded-for-loops-in-julia/130728/7 "2025-07-15T08:20:29Z")

</div>

Assuming that `f` and `g` are noticeably more expensive than the summation and that `M * N` is not larger than you can afford another array of the same size as `A`, I would sidestep the threaded reduction and try something like

```julia
B = similar(A)
@threads for i in 1:M
    @inbounds begin 
        @simd for j in 1:N 
            A[i, j] = f(i, j)
            B[i, j] = g(A[i, j])
        end
    end
end
ans = sum(B)

```

---

<div class="post-metadata">

### Author: ![random\_guy](https://avatars.discourse-cdn.com/v4/letter/r/e0b2c6/32.png) [@random\_guy](https://discourse.julialang.org/u/random_guy)
#### Post date: [July 15, 2025, 8:27am UTC](https://discourse.julialang.org/t/multithreaded-for-loops-in-julia/130728/8 "2025-07-15T08:27:26Z")

</div>

Thank you. In my actual use case, M and N will be quite large and f and g will be pretty inexpensive, but I will keep this in mind for the future.

---

<div class="post-metadata">

### Author: ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)
#### Post date: [July 15, 2025, 8:36am UTC](https://discourse.julialang.org/t/multithreaded-for-loops-in-julia/130728/9 "2025-07-15T08:36:37Z")

</div>

You can also do a partial reduction inside the threaded loop, which might fit better to your problem.

```julia
B = similar(A, M)
@threads for i in 1:M
    @inbounds begin
        s = 0.0 
        @simd for j in 1:N 
            A[i, j] = f(i, j)
            s += g(A[i, j])
        end
        B[i] = s
    end
end
ans = sum(B)

```

---

<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: [July 15, 2025, 9:31am UTC](https://discourse.julialang.org/t/multithreaded-for-loops-in-julia/130728/10 "2025-07-15T09:31:15Z")

</div>

> [@yolhan\_mannes](#):
>
> It’s not recommended to rely on threadid that’s all 😉

The context for this is that tasks can get rescheduled to different threads (which changes their threadid).

At the moment, rescheduling can only happen if the task yields. However, whether `f(...)` yields is an implementation detail, and a pretty bad abstraction – you don’t want your code to break because you added a debug log statement in a very rare edge-case that then happens to take a lock for IO that happened to be sufficiently contested that the task yields. But if you must, then it’s still feasible to reason through whether `f` can yield (GC doesn’t yield, phew!).

---

<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: [July 15, 2025, 1:40pm UTC](https://discourse.julialang.org/t/multithreaded-for-loops-in-julia/130728/11 "2025-07-15T13:40:06Z")

</div>

Just in case: you’re putting all these code snippets inside a function, right? Right?

The hardest part about multithreading is that the “optimal” structure is highly task (and system) dependent. So, yes, there are lots of possible idioms. Which one is best for you will depend upon how big your “inner” tasks are, how much coordination the threads require, and how much your system is already limited by things like memory bandwidth.

---

<div class="post-metadata">

### Author: ![random\_guy](https://avatars.discourse-cdn.com/v4/letter/r/e0b2c6/32.png) [@random\_guy](https://discourse.julialang.org/u/random_guy)
#### Post date: [July 15, 2025, 1:52pm UTC](https://discourse.julialang.org/t/multithreaded-for-loops-in-julia/130728/12 "2025-07-15T13:52:21Z")

</div>

Haha yes of course, thanks for checking.
