parquet_auto_thread_count Function

public function parquet_auto_thread_count(cap, area) result(n)

Uses

The library's one copy of the automatic thread rule: how many threads an operation that was given no explicit threads= should use right now, under a caller-supplied cap.

omp_get_max_threads() when the caller is not inside an OpenMP parallel region, and 1 when they are, because a nested region is the caller's business. This picks a DEFAULT and refuses nothing: an explicit threads= is still honoured inside a region, which is the distinction CLAUDE.md's "Auto-threading: omp_in_parallel() picks a DEFAULT" note draws. Without it, T OpenMP threads would each ask for T more, and T*T oversubscription is slower than not threading at all.

The predicate is omp_get_level, NOT omp_in_parallel, and the difference is not pedantic. omp_in_parallel answers "is the enclosing region ACTIVE", i.e. does its team have more than one thread. It is therefore .false. inside a region that exists but runs on one thread -- !$omp parallel if(cond) with cond false, or any region at all under OMP_NUM_THREADS=1. That is still a nested region, and the rule above still applies to it, so the old spelling let every such caller open a full team one level down. It also deadlocks libgomp; see parquet_nested_team_unsafe below and feature_risks.md Risk-104.

The cap only ever LOWERS the answer, and never overrides the parallel-region rule -- a caller who capped sorting at 8 said nothing about what should happen inside someone else's parallel region, and lifting the serial answer back to 8 there is exactly the T*T oversubscription the rule exists to prevent. cap <= 0 means "no cap", which is how every cfg_*_threads knob spells its automatic default.

Never report more threads than can actually run. omp_get_max_threads answers an ICV, which is what the environment ASKED for; omp_get_num_procs answers what this thread's affinity mask allows. They differ whenever the initial thread was bound before main.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: cap

caller's domain cap; <= 0 means no cap

character(len=*), intent(in) :: area

subsystem name, for the affinity-clamp warning

Return Value integer


Source Code

    integer function parquet_auto_thread_count(cap, area) result(n)
#ifdef _OPENMP
        use omp_lib, only: omp_get_max_threads, omp_get_level
#endif
        integer, intent(in) :: cap             !! caller's domain cap; `<= 0` means no cap
        character(len=*), intent(in) :: area   !! subsystem name, for the affinity-clamp warning
        n = 1
#ifdef _OPENMP
        if (omp_get_level() == 0) n = omp_get_max_threads()
#endif
        if (cap > 0 .and. cap < n) n = cap
        n = parquet_clamp_to_affinity(n, area)
    end function parquet_auto_thread_count