# Evaluation order of Threads.nthreads()

**URL:** <https://discourse.julialang.org/t/evaluation-order-of-threads-nthreads/121989>\
**Category:** General Usage\
**Tags:** question\
**Created:** [October 30, 2024, 11:59am UTC](https://discourse.julialang.org/t/evaluation-order-of-threads-nthreads/121989 "2024-10-30T11:59:58Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![lkdvos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lkdvos/32/43091_2.png) [@lkdvos](https://discourse.julialang.org/u/lkdvos)\
**Post date:** [October 30, 2024, 11:59am UTC](https://discourse.julialang.org/t/evaluation-order-of-threads-nthreads/121989/1 "2024-10-30T11:59:58Z")

</div>

I have found some unexpected behavior when trying to capture the result of `Threads.nthreads()`. The use-case is the following:

```julia
module MyModule
# some algorithms that may or may not use multithreading

# Default settings controlling the algorithms
module Defaults
const ntasks = Threads.nthreads()
end
end

```

Interestingly, with this design, I get the following output, even when starting julia with multiple threads:

```julia-repl
julia> Threads.nthreads()
8

julia> using MyModule; MyModule.Defaults.ntasks
1

```

It seems like the const value is computed before the `Threads.nthreads()` takes on its value, so I must be missing something here. Is this expected behavior? Does this mean that if I want to have access to `nthreads`, I would have to either use a function call, or some form of ` __init__ ` procedure?

---

<div class="post-metadata">

**Author:** ![littlelib](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/littlelib/32/209324_2.png) [@littlelib](https://discourse.julialang.org/u/littlelib)\
**Post date:** [October 30, 2024, 12:22pm UTC](https://discourse.julialang.org/t/evaluation-order-of-threads-nthreads/121989/2 "2024-10-30T12:22:18Z")

</div>

Yes, using ` __init__ ` will do.

It seems that your module was first precompiled in a single threaded context. The codes inside the module will not be reevaluated even if you restart, hence ntasks will always equal 1 no matter how many threads you restart julia with.

You can use ` __init__ ` to execute a code whenever the module is loaded.  
For more info, I believe @oxinabox 's [post](https://www.oxinabox.net/2023/06/16/top-level-code-in-julia.html) will be helpful.

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [October 30, 2024, 12:29pm UTC](https://discourse.julialang.org/t/evaluation-order-of-threads-nthreads/121989/3 "2024-10-30T12:29:54Z")

</div>

Maybe you want to elaborate what you want to ultimately achieve. This sounds like a potential [XY problem](https://xyproblem.info/).

My understanding is that you want to “cache” the value of `Threads.nthreads()`, but that’s such a quick function that caching it is probably not worth the effort (and the risk of doing it wrong):

```julia
julia> @benchmark Threads.nthreads()
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min … max): 1.742 ns … 9.479 ns ┊ GC (min … max): 0.00% … 0.00%
 Time (median): 1.749 ns ┊ GC (median): 0.00%
 Time (mean ± σ): 1.756 ns ± 0.115 ns ┊ GC (mean ± σ): 0.00% ± 0.00%

   ▅█                                                        
  ▅██▄▂▂▁▂▂▁▂▁▁▂▂▁▁▂▁▁▁▂▂▂▁▁▁▂▂▁▁▁▁▁▁▁▂▂▂▂▂▁▁▁▁▁▁▁▂▁▂▂▁▂▁▂▂ ▂
  1.74 ns Histogram: frequency by time 1.93 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

```

Also, keep in mind that the number of Julia threads currently can’t be changed after a Julia session is started, but that restriction may be lifted at some point in the future, which makes caching the value of `nthreads()` ill-advised.

---

<div class="post-metadata">

**Author:** ![lkdvos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lkdvos/32/43091_2.png) [@lkdvos](https://discourse.julialang.org/u/lkdvos)\
**Post date:** [November 3, 2024, 1:33pm UTC](https://discourse.julialang.org/t/evaluation-order-of-threads-nthreads/121989/4 "2024-11-03T13:33:29Z")

</div>

Thanks for that link to @oxinabox 's post, that’s definitely the information I was looking for!

@giordano , in all honesty, I really was mostly looking for information to understand the behavior, not so much a solution to the specific problem. My apologies if my question did not fully reflect this. For completeness, the specific pattern I had involves a structure like this:

```julia
module Defaults
using OhMyThreads
const maxiter = 100
const tol = 1e-6
const scheduler = Threads.nthreads() == 1 ? SerialScheduler() : DynamicScheduler()
# and more default settings
end

function myalgorithm(args...; tol=Defaults.tol, maxiter=Defaults.maxiter, ntasks=Defaults.ntasks)
   # implementation
end

```

Specifically, I have some defaults for a number of algorithms that I like keeping in a centralized spot of the repository, ie a module `Defaults`. Naively putting the call to `Threads.nthreads()` doesn’t work due to the explanations you gave me, and for consistency it’s less nice (although completely okay) to have some defaults being variables, and others being ones that you have to call.  
It really has not a lot to do with speed, more than code aesthetics, convenience and consistency, and mostly with me understanding why something works or not. Thanks though!
