env.hh
Go to the documentation of this file.
1#pragma once
2#include <batchlas/export.hh>
3#include <cstdlib>
4#include <string>
5
6/// @file
7/// @brief The shared environment-variable parsers and the ScopedEnvVar RAII setter.
8///
9/// These parsers define the exact spellings that `BATCHLAS_*` knobs accept; batchlas::settings()
10/// calls them for every typed field. The accepted sets are the contract: widening one would
11/// change how every existing call site reads the same strings.
12/// @see @ref design_environment
13/// @ingroup api_config
14
15namespace batchlas {
16
17// Declared, not included: this header is reached by nearly every device TU, and the declaration
18// is all ScopedEnvVar needs.
19namespace detail {
20BATCHLAS_API void reload_settings();
21}
22
23/// @brief True when `v` is exactly one of `1`, `true`, `TRUE`, `on`, `ON`.
24/// @param v the variable's value (`std::getenv(...)`), not its name; `nullptr` means unset
25/// @return false for an unset variable and for every other spelling
26/// @ingroup api_config_lowlevel
27// Takes the VALUE. A name-taking overload once existed and made env_truthy("BATCHLAS_X") silently
28// always false. evidence: docs/design/environment.md#environment-the-shared-parsers-in-envhh
29inline bool env_truthy(const char* v) {
30 if (!v) return false;
31 const std::string s(v);
32 return (s == "1" || s == "true" || s == "TRUE" || s == "on" || s == "ON");
33}
34
35/// @brief True when `v` is exactly one of `0`, `false`, `FALSE`, `off`, `OFF`.
36///
37/// Not `!env_truthy(v)`: an unset variable is neither truthy nor falsy, which lets a caller
38/// distinguish "forced off" from "not specified".
39/// @param v the variable's value, or `nullptr` when unset
40/// @return false for an unset variable and for every other spelling
41/// @ingroup api_config_lowlevel
42// A knob that wants "Off"/"No" must case-fold its own value (sytrd_sb2st_hh.cc does); do not
43// fold that helper back into this one.
44inline bool env_falsy(const char* v) {
45 if (!v) return false;
46 const std::string s(v);
47 return (s == "0" || s == "false" || s == "FALSE" || s == "off" || s == "OFF");
48}
49
50/// @brief The integer value of environment variable `name`.
51/// @param name the variable's name
52/// @param fallback returned when the variable is unset or `std::stoi` rejects it
53/// @return the parsed value; note that `std::stoi` accepts a numeric prefix (`"16x"` is 16)
54/// @ingroup api_config_lowlevel
55inline int env_int_or(const char* name, int fallback) {
56 const char* v = std::getenv(name);
57 if (!v) return fallback;
58 try {
59 return std::stoi(std::string(v));
60 } catch (...) {
61 return fallback;
62 }
63}
64
65/// @brief As env_int_or(), but a value <= 0 also yields `fallback`.
66///
67/// The shape of every kernel-geometry knob: a forced work-group count, tile width or sub-group
68/// count is meaningless at zero or below.
69/// @param name the variable's name
70/// @param fallback returned when unset, unparseable or non-positive
71/// @ingroup api_config_lowlevel
72inline int env_positive_int_or(const char* name, int fallback) {
73 const int v = env_int_or(name, fallback);
74 return v > 0 ? v : fallback;
75}
76
77/// @brief The value of environment variable `name`, or `fallback` when it is unset or empty.
78/// @ingroup api_config_lowlevel
79inline std::string env_string_or(const char* name, const std::string& fallback) {
80 const char* v = std::getenv(name);
81 if (!v || !*v) return fallback;
82 return std::string(v);
83}
84
85/// @brief Sets (or unsets) an environment variable for a scope and restores it on exit.
86///
87/// Both the constructor and the destructor call detail::reload_settings(), so the library sees
88/// the pinned value immediately and stops seeing it when the scope ends. A raw `::setenv` is
89/// invisible to batchlas::settings(); use this instead.
90/// @code
91/// {
92/// ScopedEnvVar pin("BATCHLAS_GEMM_ROUTE", "native");
93/// gemm(ctx, a, b, c, GemmOptions<float>{}); // runs the native kernel
94/// }
95/// @endcode
96/// @pre `name` outlives the object (in practice a string literal); it is borrowed, not copied.
97/// @warning Not thread-safe, because the process environment is not: construct from a test body
98/// or benchmark setup, never inside a parallel region. Do not let one straddle a
99/// `*_buffer_size()` query and its solve.
100/// @see @ref design_environment
101/// @ingroup api_config
102// Name borrowed so no heap allocation lands inside timed benchmark lambdas.
103// evidence: docs/design/environment.md#environment-scopedenvvar
105public:
106 /// @brief Pin `name` to `value` for the scope.
107 /// @param name the variable's name
108 /// @param value the value to set, or `nullptr` to unset the variable for the duration (which
109 /// asks for the automatic route regardless of the surrounding environment)
110 ScopedEnvVar(const char* name, const char* value) : name_(name) {
111 if (const char* old = std::getenv(name_)) {
112 old_value_ = old;
113 had_old_value_ = true;
114 }
115 if (value) {
116 ::setenv(name_, value, 1);
117 } else {
118 ::unsetenv(name_);
119 }
121 }
122
123 /// @brief Restore the previous value (or unset state) and reload the settings.
125 if (had_old_value_) {
126 ::setenv(name_, old_value_.c_str(), 1);
127 } else {
128 ::unsetenv(name_);
129 }
130 // Nested instances restore innermost-first, so this reload matches the enclosing scope.
132 }
133
134 // Copying would restore the same variable twice, the second time from a stale snapshot.
135 ScopedEnvVar(const ScopedEnvVar&) = delete;
137
138private:
139 const char* name_;
140 std::string old_value_;
141 bool had_old_value_ = false;
142};
143
144} // namespace batchlas
ScopedEnvVar(const char *name, const char *value)
Pin name to value for the scope.
Definition env.hh:110
ScopedEnvVar & operator=(const ScopedEnvVar &)=delete
ScopedEnvVar(const ScopedEnvVar &)=delete
~ScopedEnvVar()
Restore the previous value (or unset state) and reload the settings.
Definition env.hh:124
int env_int_or(const char *name, int fallback)
The integer value of environment variable name.
Definition env.hh:55
std::string env_string_or(const char *name, const std::string &fallback)
The value of environment variable name, or fallback when it is unset or empty.
Definition env.hh:79
bool env_falsy(const char *v)
True when v is exactly one of 0, false, FALSE, off, OFF.
Definition env.hh:44
bool env_truthy(const char *v)
True when v is exactly one of 1, true, TRUE, on, ON.
Definition env.hh:29
int env_positive_int_or(const char *name, int fallback)
As env_int_or(), but a value <= 0 also yields fallback.
Definition env.hh:72
void reload_settings()
Re-read the environment on top of the last configure() (or the defaults).