NAME

OpenMP::Environment::Validation - portable OpenMP 5.2 and GNU libgomp environment validation

SYNOPSIS

use OpenMP::Environment::Validation qw/
    validate_value assert_environment analyze_environment
/;

my $schedule = validate_value(
    q{OMP_SCHEDULE},
    q{nonmonotonic:dynamic,4},
);

assert_environment(\%ENV);  # dies on malformed or conflicting settings

my $report = analyze_environment(\%ENV);
print $report->{valid} ? "valid\n" : "needs attention\n";

PURPOSE

OpenMP::Environment::Validation contains the validation policy used by OpenMP::Environment. It is intentionally separate from the public accessor/DSL module so the policy can be read, tested, and reused on its own.

The validation reference point is OpenMP 5.2 together with GNU libgomp as shipped/documented with GCC 16.2.0. The module distinguishes between:

  • INVALID

    A value does not satisfy this module's selected validation profile: the OpenMP 5.2 grammar, plus an explicitly documented GCC/libgomp restriction when GNU's documented grammar is narrower. Such GNU-profile restrictions are called out individually rather than being presented as portable OpenMP requirements.

  • CONFLICT / IMPLEMENTATION-DEFINED COMBINATION

    Each individual value is syntactically valid, but OpenMP explicitly says the combination is implementation-defined. The principal 5.2 case handled here is OMP_NESTED=FALSE together with OMP_MAX_ACTIVE_LEVELS greater than one.

  • VALID BUT RUNTIME-DEPENDENT

    The syntax is valid but whether the request can be honored depends on runtime resources, topology, target devices, allocators, or implementation limits. These values pass validation and are reported by analyze_environment.

PORTABILITY SCOPE AND NON-GOALS

This module is deliberately not system-aware. It does not inspect CPU counts, CPU identifiers, NUMA topology, hwloc, GPUs, target devices, available allocators, /proc, compiler executables, runtime state, or operating-system resources. Such checks can be useful, but they introduce portability and load-time concerns that belong in a future, explicitly system-aware layer.

Consequently, values such as these are syntactically valid here even though a particular runtime may be unable to honor them:

OMP_DEFAULT_DEVICE=7
OMP_PLACES={0,1,2,3}
OMP_STACKSIZE=64G
OMP_THREAD_LIMIT=100000

OPENMP VALUE SYNTAX AND NORMALIZATION

OpenMP 5.2 Chapter 21 states that OpenMP environment-variable values are generally case-insensitive and may contain leading and trailing whitespace. Strict validation therefore ignores surrounding whitespace for supported OMP_* variables before validating them. The established upper-case normalization used by OpenMP::Environment is retained for its historical boolean/token fields.

OMP_AFFINITY_FORMAT is the important exception. Section 21.2.5 explicitly states that its value is case-sensitive and that leading and trailing whitespace is significant. This module therefore preserves that string exactly.

The GOMP_* variables are GNU extensions rather than OpenMP Chapter 21 variables; their syntax follows the libgomp documentation rather than assuming that every general OpenMP lexical rule applies to them.

API

validate_value NAME, VALUE

Validates one supported OMP_* or GOMP_* value and returns the value after normalization. For OMP_* values, surrounding whitespace is ignored except for OMP_AFFINITY_FORMAT, where it is significant. The same six variables upper-cased by older OpenMP::Environment releases continue to be upper-cased. Dies on invalid input.

validate_assignment NAME, VALUE

Applies the validation policy used by ordinary/lvalue assignment in OpenMP::Environment. To preserve pre-1.5.0 compatibility, variables that were historically pass-through remain pass-through here. Use validate_value or assert for strict grammar validation of all supported variables.

assert_variable ENV, NAME

Validates one value from a hash reference and checks cross-variable conflicts that involve that variable. An unset variable is valid.

assert_environment ENV

Validates every supported variable present in the supplied hash and then checks portable cross-variable conflicts. As with historical assert_omp_environment, normalized values are written back to the hash.

analyze_environment ENV

Returns a machine-readable hash reference with these keys:

valid
errors
conflicts
runtime_dependent
notes

It never performs host/resource discovery.

validation_rules

Returns introspection metadata describing the supported fields, historical upper-case normalization, variables validated on ordinary assignment, fields whose whitespace is significant, validator routines, and the validation profile. This is intended to make the policy useful to machine consumers as well as to human readers of this POD.

PER-VARIABLE REFERENCE

OMP_NUM_THREADS

OpenMP 5.2 Section 21.1.2 permits one positive integer or a comma-separated list for nested parallel levels. GCC/libgomp implements that syntax. Values larger than runtime capability are implementation-dependent, so this module checks only the positive-integer grammar.

Valid:   OMP_NUM_THREADS=8
Valid:   OMP_NUM_THREADS=8,4,2
Invalid: OMP_NUM_THREADS=8,0,2

GCC/libgomp: https://gcc.gnu.org/onlinedocs/gcc-16.2.0/libgomp/OMP_005fNUM_005fTHREADS.html

OpenMP 5.2: https://www.openmp.org/spec-html/5.2/openmp.html, Section 21.1.2.

OMP_MAX_ACTIVE_LEVELS

OpenMP 5.2 Section 21.1.4 permits a non-negative integer, so zero is valid according to the OpenMP grammar. GCC/libgomp documents this environment variable more narrowly as a positive integer. Earlier OpenMP::Environment releases also rejected zero. Because this distribution is explicitly profiled against GCC 16.2/libgomp, strict validation retains the GNU/legacy positive-integer rule.

Valid in this GCC/libgomp profile: OMP_MAX_ACTIVE_LEVELS=1
OpenMP-valid but rejected here:   OMP_MAX_ACTIVE_LEVELS=0
Invalid:                          OMP_MAX_ACTIVE_LEVELS=-1

Values above the maximum nesting level supported by a particular runtime are implementation-defined and are not system-probed here.

GCC/libgomp: https://gcc.gnu.org/onlinedocs/gcc-16.2.0/libgomp/OMP_005fMAX_005fACTIVE_005fLEVELS.html

OpenMP 5.2: Section 21.1.4 and Appendix A.

OMP_PROC_BIND

OpenMP 5.2 Section 21.1.7 specifies TRUE, FALSE, or a list of PRIMARY, CLOSE, and SPREAD. OpenMP deprecates the older MASTER spelling; GNU libgomp deliberately retains it, so this module accepts it. Binding to actual places and the policy chosen for TRUE remain implementation-dependent.

Valid:   OMP_PROC_BIND=close
Valid:   OMP_PROC_BIND=spread,close,primary
GNU:     OMP_PROC_BIND=master,close,spread
Invalid: OMP_PROC_BIND=near

GCC/libgomp: https://gcc.gnu.org/onlinedocs/gcc-16.2.0/libgomp/OMP_005fPROC_005fBIND.html

OpenMP 5.2: Section 21.1.7 and Appendix A.

OMP_PLACES

OpenMP 5.2 Section 21.1.6 defines abstract names, explicit place/resource lists, intervals, strides, and exclusions. It intentionally leaves resource numbering, exact abstract-name meaning, and additional abstract names to the implementation. GNU libgomp documents threads, cores, sockets, ll_caches, and numa_domains plus explicit list syntax.

Valid:   OMP_PLACES=cores
Valid:   OMP_PLACES=cores(4)
Valid:   OMP_PLACES={0,1,2},{3,4,5}
Valid:   OMP_PLACES={0:4},{4:4}
Valid:   OMP_PLACES=!{0},1:3
Invalid: OMP_PLACES={0,,2}

This module checks grammar but does not decide whether processor 4 exists or what cores means on the current machine.

GCC/libgomp: https://gcc.gnu.org/onlinedocs/gcc-16.2.0/libgomp/OMP_005fPLACES.html

OpenMP 5.2: Section 21.1.6 and Appendix A.

OMP_SCHEDULE

OpenMP 5.2 Section 21.2.1 defines:

[modifier:]kind[,chunk]

where modifier is MONOTONIC or NONMONOTONIC, kind is STATIC, DYNAMIC, GUIDED, or AUTO, and chunk is a positive integer. GNU libgomp documentation emphasizes the simpler type[,chunk] spelling; the full OpenMP 5.2 grammar is accepted here because it includes all GNU-documented forms.

Valid:   OMP_SCHEDULE=dynamic,4
Valid:   OMP_SCHEDULE=monotonic:guided,8
Invalid: OMP_SCHEDULE=banana
Invalid: OMP_SCHEDULE=dynamic,0

OpenMP specifies implementation-defined behavior for malformed values; this module instead rejects malformed values early.

OMP_STACKSIZE and GOMP_STACKSIZE

OpenMP 5.2 Section 21.2.2 specifies a positive size with optional B, K, M, or G unit for OMP_STACKSIZE; libgomp uses kilobytes when the unit is omitted. Whether the requested stack can actually be provided is implementation-dependent and is not checked.

GNU GOMP_STACKSIZE is an extension documented as a positive numeric value in kilobytes, with no unit suffix. Older OpenMP::Environment releases did not validate this variable, and the unchanged regression suite includes and asserts a unit-suffixed value. Version 1.5.0 therefore accepts B, K, M, and G suffixes as an explicit OpenMP::Environment compatibility extension in both assignment and assertion. This POD does not claim those suffixes are valid libgomp GOMP_STACKSIZE syntax; the GNU-native spelling is an unsuffixed positive integer interpreted as kilobytes.

OMP_ALLOCATOR

OpenMP 5.2 Section 21.5.1 and Sections 6.1-6.2 define predefined allocators, predefined memory spaces, and allocator traits. This module checks the trait vocabulary and intrinsic constraints including positive power-of-two alignment, positive pool_size, booleans, fallback values, and predefined allocator traits. OpenMP permits fb_data for allocator_fb. GNU libgomp still lists allocator_fb as an allowed fallback token, but explicitly marks fb_data unsupported in the OMP_ALLOCATOR environment string because it requires an allocator handle. Strict validation therefore accepts the documented fallback=allocator_fb token, rejects an explicit fb_data trait, and deliberately does not infer whether a useful allocator fallback can be constructed without fb_data. Ordinary assignment remains pass-through for compatibility.

Valid: OMP_ALLOCATOR=omp_high_bw_mem_alloc
Valid: OMP_ALLOCATOR=omp_large_cap_mem_space:alignment=16,pinned=true
Valid: OMP_ALLOCATOR=omp_low_lat_mem_space:fallback=allocator_fb
GNU:   OMP_ALLOCATOR=ompx_gnu_pinned_mem_alloc
Invalid: OMP_ALLOCATOR=omp_low_lat_mem_space:alignment=3
libgomp-invalid: OMP_ALLOCATOR=omp_default_mem_space:fb_data=omp_default_mem_alloc

OpenMP explicitly leaves actual storage-resource mappings, some predefined allocator memory-space associations, partition minimums, and the default pool size implementation-defined. GNU libgomp maps the cgroup/pteam/thread allocators to omp_low_lat_mem_space as an implementation choice and also provides ompx_gnu_pinned_mem_alloc, ompx_gnu_managed_mem_alloc, and ompx_gnu_managed_mem_space as GNU extensions. Availability is not probed.

Memory allocator trait definitions: https://www.openmp.org/spec-html/5.2/openmpse35.html

OMP_AFFINITY_FORMAT

OpenMP 5.2 Section 21.2.5 specifies a percent-field format and permits implementation-defined additional field types. A field width is a positive decimal integer and can be written as a bare minimum width (%4L), as a right-justified width (%.4L), or with zero padding for numeric fields (%0.4L). GNU libgomp documents the same width forms and the standard short and long field names. Syntactically valid unknown alphabetic field names are accepted as possible implementation extensions.

The value is case-sensitive and leading/trailing whitespace is significant; strict validation preserves it rather than applying the general OpenMP whitespace normalization. OpenMP says the result is unspecified when the zero-padding modifier is used for a nonnumeric field; that is not a syntax error, so this validator does not reject it.

Valid:   OMP_AFFINITY_FORMAT=thread %n affinity %A
Valid:   OMP_AFFINITY_FORMAT=level %4L thread %0.2n
Valid:   OMP_AFFINITY_FORMAT=host %.12{host}
Valid:   OMP_AFFINITY_FORMAT=%% %n
Invalid: OMP_AFFINITY_FORMAT=thread %
Invalid: OMP_AFFINITY_FORMAT=level %.0L

GOMP_CPU_AFFINITY

This is a GNU extension, not an OpenMP environment variable. libgomp accepts space/comma-separated CPU numbers, ranges M-N, and stride ranges M-N:S. OMP_PROC_BIND has precedence when both variables are set.

Valid:   GOMP_CPU_AFFINITY=0 3 1-2 4-15:2
Invalid: GOMP_CPU_AFFINITY=cpu0

CPU existence is not checked.

GOMP_SPINCOUNT

This GNU extension accepts INFINITE, INFINITY, or a non-negative integer optionally suffixed by k, M, G, or T. Effective busy-wait behavior can depend on OMP_WAIT_POLICY and available CPUs; only syntax is checked.

Valid:   GOMP_SPINCOUNT=300000
Valid:   GOMP_SPINCOUNT=30G
Valid:   GOMP_SPINCOUNT=INFINITY
Invalid: GOMP_SPINCOUNT=forever

GOMP_RTEMS_THREAD_POOLS

This GNU/RTEMS-only variable uses colon-separated count[$priority]@scheduler configurations. The documented libgomp example 1@WRK0:3$4@WRK1 is valid. Scheduler existence and permissible RTEMS priority ranges are not queried.

Other scalar and token variables

The remaining standard variables use smaller grammars but still have implementation-defined edges worth distinguishing from syntax errors:

  • OMP_CANCELLATION and OMP_DISPLAY_AFFINITY

    TRUE or FALSE. OpenMP makes other values implementation-defined for OMP_CANCELLATION and makes the display action implementation-defined for other OMP_DISPLAY_AFFINITY values.

  • OMP_DISPLAY_ENV

    TRUE, FALSE, or VERBOSE. OpenMP says the displayed information is unspecified for other values.

  • OMP_DEFAULT_DEVICE and OMP_MAX_TASK_PRIORITY

    Non-negative integers. Device existence and runtime priority capability are not probed.

  • OMP_DYNAMIC and deprecated OMP_NESTED

    OpenMP defines boolean values. OpenMP::Environment additionally retains its historical 1/0 compatibility. OMP_NESTED also participates in the cross-variable rule documented below.

  • OMP_NUM_TEAMS, OMP_TEAMS_THREAD_LIMIT, and OMP_THREAD_LIMIT

    Positive integers. OpenMP makes behavior implementation-defined when a value is invalid or exceeds an implementation limit; this module validates syntax but does not query those limits.

  • OMP_TARGET_OFFLOAD

    MANDATORY, DISABLED, or DEFAULT. OpenMP 5.2 makes support of DISABLED implementation-defined; GCC/libgomp explicitly implements all three values.

  • OMP_WAIT_POLICY

    ACTIVE or PASSIVE. The detailed waiting behavior is implementation- defined.

  • GOMP_DEBUG

    GNU extension accepting 0 or 1.

CROSS-VARIABLE RULES

OMP_NESTED and OMP_MAX_ACTIVE_LEVELS

OpenMP 5.2 explicitly says behavior is implementation-defined when both are set, OMP_NESTED is false, and OMP_MAX_ACTIVE_LEVELS is greater than one. assert_environment treats this as a conflict:

OMP_NESTED=FALSE
OMP_MAX_ACTIVE_LEVELS=4

If both are set without that conflict, OpenMP says OMP_NESTED has no effect.

OMP_NUM_THREADS / OMP_PROC_BIND nesting lists

Multiple list elements can affect initialization of max-active-levels-var. OpenMP 5.2 Section 2.2 describes that ICV as depending on OMP_MAX_ACTIVE_LEVELS, OMP_NESTED, OMP_NUM_THREADS, and OMP_PROC_BIND. A list is not itself an error; analyze_environment records the relationship as a note.

OMP_PROC_BIND and GOMP_CPU_AFFINITY

GNU libgomp gives OMP_PROC_BIND precedence if both are set. This is a valid configuration, not a conflict; analyze_environment records the precedence.

IMPLEMENTATION-DEFINED VERSUS GNU CHOICES

OpenMP deliberately leaves several matters to implementations. Important examples include processor numbering and abstract OMP_PLACES meanings, actual affinity policy for OMP_PROC_BIND=TRUE, maximum supported thread and active-level counts, ability to provide a requested stack, memory-space mappings for several predefined allocators, allocator pool defaults, and the details of active/passive waiting.

GNU libgomp necessarily chooses concrete behavior in many of those areas and also provides GOMP_* extensions. This module validates GNU-documented syntax where it is portable to do so, but it does not turn a GNU runtime choice into a supposed cross-platform OpenMP guarantee.

The OpenMP implementation-defined behavior index is: https://www.openmp.org/spec-html/5.2/openmpap1.html.

The GCC/libgomp environment-variable index is: https://gcc.gnu.org/onlinedocs/gcc-16.2.0/libgomp/Environment-Variables.html.

COPYRIGHT AND LICENSE

Same as Perl.