defaults.hpp
1 /*
2  * Copyright (c) 2022-2023, NVIDIA CORPORATION.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include <algorithm>
19 #include <cstddef>
20 #include <cstdlib>
21 #include <sstream>
22 #include <stdexcept>
23 #include <string>
24 #include <utility>
25 
26 #include <kvikio/shim/cufile.hpp>
27 #include <kvikio/thread_pool.hpp>
28 
29 namespace kvikio {
30 namespace detail {
31 
32 template <typename T>
33 T getenv_or(std::string_view env_var_name, T default_val)
34 {
35  const auto* env_val = std::getenv(env_var_name.data());
36  if (env_val == nullptr) { return default_val; }
37 
38  std::stringstream sstream(env_val);
39  T converted_val;
40  sstream >> converted_val;
41  if (sstream.fail()) {
42  throw std::invalid_argument("unknown config value " + std::string{env_var_name} + "=" +
43  std::string{env_val});
44  }
45  return converted_val;
46 }
47 
48 template <>
49 inline bool getenv_or(std::string_view env_var_name, bool default_val)
50 {
51  const auto* env_val = std::getenv(env_var_name.data());
52  if (env_val == nullptr) { return default_val; }
53  try {
54  // Try parsing `env_var_name` as a integer
55  return static_cast<bool>(std::stoi(env_val));
56  } catch (const std::invalid_argument&) {
57  }
58  // Convert to lowercase
59  std::string str{env_val};
60  std::transform(str.begin(), str.end(), str.begin(), ::tolower);
61  // Trim whitespaces
62  std::stringstream trimmer;
63  trimmer << str;
64  str.clear();
65  trimmer >> str;
66  // Match value
67  if (str == "true" || str == "on" || str == "yes") { return true; }
68  if (str == "false" || str == "off" || str == "no") { return false; }
69  throw std::invalid_argument("unknown config value " + std::string{env_var_name} + "=" +
70  std::string{env_val});
71 }
72 
73 } // namespace detail
74 
79 class defaults {
80  private:
81  kvikio::third_party::thread_pool _thread_pool{get_num_threads_from_env()};
82  bool _compat_mode;
83  std::size_t _task_size;
84  std::size_t _gds_threshold;
85 
86  static unsigned int get_num_threads_from_env()
87  {
88  const int ret = detail::getenv_or("KVIKIO_NTHREADS", 1);
89  if (ret <= 0) { throw std::invalid_argument("KVIKIO_NTHREADS has to be a positive integer"); }
90  return ret;
91  }
92 
93  defaults()
94  {
95  // Determine the default value of `compat_mode`
96  {
97  if (std::getenv("KVIKIO_COMPAT_MODE") != nullptr) {
98  // Setting `KVIKIO_COMPAT_MODE` take precedence
99  _compat_mode = detail::getenv_or("KVIKIO_COMPAT_MODE", false);
100  } else {
101  // If `KVIKIO_COMPAT_MODE` isn't set, we infer based on runtime environment
102  _compat_mode = !is_cufile_available();
103  }
104  }
105  // Determine the default value of `task_size`
106  {
107  const ssize_t env = detail::getenv_or("KVIKIO_TASK_SIZE", 4 * 1024 * 1024);
108  if (env <= 0) {
109  throw std::invalid_argument("KVIKIO_TASK_SIZE has to be a positive integer");
110  }
111  _task_size = env;
112  }
113  // Determine the default value of `gds_threshold`
114  {
115  const ssize_t env = detail::getenv_or("KVIKIO_GDS_THRESHOLD", 1024 * 1024);
116  if (env <= 0) {
117  throw std::invalid_argument("KVIKIO_GDS_THRESHOLD has to be a positive integer");
118  }
119  _gds_threshold = env;
120  }
121  }
122 
123  static defaults* instance()
124  {
125  static defaults _instance;
126  return &_instance;
127  }
128 
129  public:
148  [[nodiscard]] static bool compat_mode() { return instance()->_compat_mode; }
149 
158  static void compat_mode_reset(bool enable) { instance()->_compat_mode = enable; }
159 
170  {
171  return instance()->_thread_pool;
172  }
173 
182  [[nodiscard]] static unsigned int thread_pool_nthreads()
183  {
184  return thread_pool().get_thread_count();
185  }
186 
196  static void thread_pool_nthreads_reset(unsigned int nthreads) { thread_pool().reset(nthreads); }
197 
206  [[nodiscard]] static std::size_t task_size() { return instance()->_task_size; }
207 
213  static void task_size_reset(std::size_t nbytes) { instance()->_task_size = nbytes; }
214 
226  [[nodiscard]] static std::size_t gds_threshold() { return instance()->_gds_threshold; }
227 
232  static void gds_threshold_reset(std::size_t nbytes) { instance()->_gds_threshold = nbytes; }
233 };
234 
235 } // namespace kvikio
Singleton class of default values used thoughtout KvikIO.
Definition: defaults.hpp:79
static std::size_t task_size()
Get the default task size used for parallel IO operations.
Definition: defaults.hpp:206
static void gds_threshold_reset(std::size_t nbytes)
Reset the default GDS threshold, which is the minimum size to use GDS (in bytes).
Definition: defaults.hpp:232
static void compat_mode_reset(bool enable)
Reset the value of kvikio::defaults::compat_mode()
Definition: defaults.hpp:158
static void task_size_reset(std::size_t nbytes)
Reset the default task size used for parallel IO operations.
Definition: defaults.hpp:213
static bool compat_mode()
Return whether the KvikIO library is running in compatibility mode or not.
Definition: defaults.hpp:148
static void thread_pool_nthreads_reset(unsigned int nthreads)
Reset the number of threads in the default thread pool. Waits for all currently running tasks to be c...
Definition: defaults.hpp:196
static kvikio::third_party::thread_pool & thread_pool()
Get the default thread pool.
Definition: defaults.hpp:169
static std::size_t gds_threshold()
Get the default GDS threshold, which is the minimum size to use GDS (in bytes).
Definition: defaults.hpp:226
static unsigned int thread_pool_nthreads()
Get the number of threads in the default thread pool.
Definition: defaults.hpp:182
A C++17 thread pool class. The user submits tasks to be executed into a queue. Whenever a thread beco...
Definition: thread_pool.hpp:54
void reset(const ui32 &_thread_count=std::thread::hardware_concurrency())
Reset the number of threads in the pool. Waits for all currently running tasks to be completed,...
ui32 get_thread_count() const
Get the number of threads in the pool.
A C++17 thread pool for high-performance scientific computing.