# Inconsistent CPU utilisation in @threads loops

**URL:** <https://discourse.julialang.org/t/inconsistent-cpu-utilisation-in-threads-loops/110512>\
**Category:** Performance\
**Tags:** parallel, multithreading, threads, threading\
**Created:** [February 21, 2024, 12:49pm UTC](https://discourse.julialang.org/t/inconsistent-cpu-utilisation-in-threads-loops/110512 "2024-02-21T12:49:19Z")\
**Posts on this page:** 1\
**Showing post:** 20

<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:** [February 23, 2024, 4:54pm UTC](https://discourse.julialang.org/t/inconsistent-cpu-utilisation-in-threads-loops/110512/20 "2024-02-23T16:54:48Z")

</div>

> [@ysh](#):
>
> I gave [OhMyThreads.jl](https://juliahub.com/ui/Packages/OhMyThreads) a try. Actually, I would like to pre-allocate one buffer matrix per thread instead of allocating as many as there are iterations. So I did this:
> 
> ```julia
> using OhMyThreads: TaskLocalValues.TaskLocalValue, tforeach, StaticScheduler
> BLAS.set_num_threads(1)
> Random.seed!(1)
> function testp(M, n)
> ws_type = typeof(EigenWs(M, rvecs=true))
> ws = TaskLocalValue{ws_type}(() -> EigenWs(M, rvecs=true))
> ms = TaskLocalValue{typeof(M)}(() -> similar(M))
> tforeach(1:n, scheduler=StaticScheduler()) do i
> m = ms[]
> m .= M # we're doing a simple copy, but m could depend on i
> LAPACK.geevx!(ws[], 'N', 'N', 'V', 'N', m)
> end
> end
> 
> ```

Why do you make `ms` a `TaskLocalValue` and then perform a (strange) copy in the “parallel loop”? In your OP, `M` was just a single input matrix?

(I think you might be confusing input data with temporary task-local buffers.)

> [@ysh](#):
>
> I suppose this is because `ms[]` or `ws[]` can trigger GC.

Not really.

> [@ysh](#):
>
> Is there a way to make each thread access an element of a pre-allocated buffer? Something like `ms[threadid()]`, but the docs say [`threadid()`](https://docs.julialang.org/en/v1/base/multi-threading/#Base.Threads.threadid) is not safe to use.

If possible, you shouldn’t think about threads but tasks as Julia implements task-based multithreading. I recommend you take a look at [JuliaUCL24/notebooks/Day3/2\_multithreading.ipynb at main · carstenbauer/JuliaUCL24 · GitHub](https://github.com/carstenbauer/JuliaUCL24/blob/main/notebooks/Day3/2_multithreading.ipynb). Instead of accessing a pre-allocated element per thread you should likely be accessing a pre-allocated element per task and that’s what `TaskLocalValue` gives you.

But to answer your question, the following creates `nthreads()` tasks each running on a different thread and accessing an element of a pre-allocated buffer without using `threadid()`.

```julia
data = rand(nthreads())
tforeach(1:nthreads(); scheduler=StaticScheduler()) do tid
    println(data[tid])
end

```

Don’t think that’s what you want to do though.

---

_[View the full topic](https://discourse.julialang.org/t/inconsistent-cpu-utilisation-in-threads-loops/110512)._
