Can I decide if a program needs thread-safety at compile time based on the threads available by the julia process?

i.e. can I do something like

const needs_thread_safety = Threads.nthreads() == 1 ? false : true

and then use the constant to compile differently if it is true or false (disabling atomics and/or locks if false)? Or do I risk something?

This will record whatever state it was during parse time. (Top level code in packages don’t get re-executed each process). So you might get stale results

Note that the zero-argument nthreads() only counts the default thread pool, not the interactive one. Not sure if the GC threads are concerned with potential data races in Julia source.

Maybe of interest: Threads.nthreads() not a compile-time constant. · Issue #34902 · JuliaLang/julia · GitHub

ok, understood, thank you. Instead constructing needs_thread_safety at runtime and then use that to disable locking and atomics (e.g. by creating parameters in a struct related to the number of threads available and use that for disparch) would be okay, right?

Yeah that seems fine

If it’s of ay interest, what I did on Turing a while back was to make the user specify a flag: Threadsafe Evaluation – Turing.jl This becomes a type parameter on the Model struct, which means that any downstream code can choose the threaded path and not worry about e.g. type instability. Basically stripped of all the bells and whistles, it looks like this:

struct Model{threaded} end
Model() = Model{false}()

# API which lets the user opt into the `threaded` path (at runtime).
setthreaded(Model) = Model{true}()

run(::Model{true}) = threaded_sum(1:10)
run(::Model{false}) = sum(1:10)

If it’s not in a perf-sensitive path, you could even make the construction of the Model type-unstable:

function Model()
    if Threads.nthreads() > 1
        Model{true}()
    else
        Model{false}()
    end
end

surely of interest! Seems like my preferred way would be the type unstable way, I’m not even sure if in my case the model construction is already type unstable since it’s not performance critical, though, if it is not, I will maybe go with a preference setting instead to preserve type stability.