libkvikio  23.12.00
driver.hpp
1 /*
2  * Copyright (c) 2021-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 <iostream>
19 #include <vector>
20 
21 #include <kvikio/error.hpp>
22 #include <kvikio/shim/cufile.hpp>
23 #include <kvikio/shim/cufile_h_wrapper.hpp>
24 
25 namespace kvikio {
26 namespace detail {
27 
28 [[nodiscard]] inline bool get_driver_flag(unsigned int prop, unsigned int flag) noexcept
29 {
30  return (prop & (1U << flag)) != 0;
31 }
32 
33 inline void set_driver_flag(unsigned int& prop, unsigned int flag, bool val) noexcept
34 {
35  if (val) {
36  prop |= (1U << flag);
37  } else {
38  prop &= ~(1U << flag);
39  }
40 }
41 } // namespace detail
42 
43 #ifdef KVIKIO_CUFILE_FOUND
44 
45 class DriverInitializer {
46  // Optional, if not used cuFiles opens the driver automatically
47  public:
48  DriverInitializer() { CUFILE_TRY(cuFileAPI::instance().DriverOpen()); }
49 
50  DriverInitializer(DriverInitializer const&) = delete;
51  DriverInitializer& operator=(DriverInitializer const&) = delete;
52  DriverInitializer(DriverInitializer&&) noexcept = delete;
53  DriverInitializer& operator=(DriverInitializer&&) noexcept = delete;
54 
55  ~DriverInitializer()
56  {
57  try {
58  CUFILE_TRY(cuFileAPI::instance().DriverClose());
59  } catch (const CUfileException& e) {
60  std::cerr << "Unable to close GDS file driver: ";
61  std::cerr << e.what();
62  std::cerr << std::endl;
63  }
64  }
65 };
66 
67 class DriverProperties {
68  private:
69  CUfileDrvProps_t _props{};
70  bool _initialized{false};
71 
72  // Because Cython does not handle exceptions in the default
73  // constructor, we initialize `_props` lazily.
74  void lazy_init()
75  {
76  if (_initialized) { return; }
77  _initialized = true;
78  CUFILE_TRY(cuFileAPI::instance().DriverGetProperties(&_props));
79  }
80 
81  public:
82  DriverProperties() = default;
83 
84  bool is_gds_available()
85  {
86  // If both the major and minor version is zero, the GDS driver isn't loaded.
87  return !(get_nvfs_major_version() == 0 && get_nvfs_minor_version() == 0);
88  }
89 
90  [[nodiscard]] unsigned int get_nvfs_major_version()
91  {
92  lazy_init();
93  return _props.nvfs.major_version;
94  }
95 
96  [[nodiscard]] unsigned int get_nvfs_minor_version()
97  {
98  lazy_init();
99  return _props.nvfs.minor_version;
100  }
101 
102  [[nodiscard]] bool get_nvfs_allow_compat_mode()
103  {
104  lazy_init();
105  return detail::get_driver_flag(_props.nvfs.dcontrolflags, CU_FILE_ALLOW_COMPAT_MODE);
106  }
107 
108  [[nodiscard]] bool get_nvfs_poll_mode()
109  {
110  lazy_init();
111  return detail::get_driver_flag(_props.nvfs.dcontrolflags, CU_FILE_USE_POLL_MODE);
112  }
113 
114  [[nodiscard]] std::size_t get_nvfs_poll_thresh_size()
115  {
116  lazy_init();
117  return _props.nvfs.poll_thresh_size;
118  }
119 
120  void set_nvfs_poll_mode(bool enable)
121  {
122  lazy_init();
123  CUFILE_TRY(cuFileAPI::instance().DriverSetPollMode(enable, get_nvfs_poll_thresh_size()));
124  detail::set_driver_flag(_props.nvfs.dcontrolflags, CU_FILE_USE_POLL_MODE, enable);
125  }
126 
127  void set_nvfs_poll_thresh_size(std::size_t size_in_kb)
128  {
129  lazy_init();
130  CUFILE_TRY(cuFileAPI::instance().DriverSetPollMode(get_nvfs_poll_mode(), size_in_kb));
131  _props.nvfs.poll_thresh_size = size_in_kb;
132  }
133 
134  [[nodiscard]] std::vector<CUfileDriverControlFlags> get_nvfs_statusflags()
135  {
136  lazy_init();
137  std::vector<CUfileDriverControlFlags> ret;
138  if (detail::get_driver_flag(_props.nvfs.dcontrolflags, CU_FILE_USE_POLL_MODE)) {
139  ret.push_back(CU_FILE_USE_POLL_MODE);
140  }
141  if (detail::get_driver_flag(_props.nvfs.dcontrolflags, CU_FILE_ALLOW_COMPAT_MODE)) {
142  ret.push_back(CU_FILE_ALLOW_COMPAT_MODE);
143  }
144  return ret;
145  }
146 
147  [[nodiscard]] std::size_t get_max_device_cache_size()
148  {
149  lazy_init();
150  return _props.max_device_cache_size;
151  }
152 
153  void set_max_device_cache_size(std::size_t size_in_kb)
154  {
155  lazy_init();
156  CUFILE_TRY(cuFileAPI::instance().DriverSetMaxCacheSize(size_in_kb));
157  _props.max_device_cache_size = size_in_kb;
158  }
159 
160  [[nodiscard]] std::size_t get_per_buffer_cache_size()
161  {
162  lazy_init();
163  return _props.per_buffer_cache_size;
164  }
165 
166  [[nodiscard]] std::size_t get_max_pinned_memory_size()
167  {
168  lazy_init();
169  return _props.max_device_pinned_mem_size;
170  }
171 
172  void set_max_pinned_memory_size(std::size_t size_in_kb)
173  {
174  lazy_init();
175  CUFILE_TRY(cuFileAPI::instance().DriverSetMaxPinnedMemSize(size_in_kb));
176  _props.max_device_pinned_mem_size = size_in_kb;
177  }
178 
179  [[nodiscard]] std::size_t get_max_batch_io_size()
180  {
181 #ifdef KVIKIO_CUFILE_BATCH_API_FOUND
182  lazy_init();
183  return _props.max_batch_io_size;
184 #else
185  return 0;
186 #endif
187  }
188 };
189 
190 #else
192  // Implement a non-default constructor to avoid `unused variable` warnings downstream
193  DriverInitializer() {}
194 };
195 
197  // Implement a non-default constructor to avoid `unused variable` warnings downstream
198  DriverProperties() {}
199 
200  static bool is_gds_available() { return false; }
201 
202  [[nodiscard]] static unsigned int get_nvfs_major_version()
203  {
204  throw CUfileException("KvikIO not compiled with cuFile.h");
205  }
206 
207  [[nodiscard]] static unsigned int get_nvfs_minor_version()
208  {
209  throw CUfileException("KvikIO not compiled with cuFile.h");
210  }
211 
212  [[nodiscard]] static bool get_nvfs_allow_compat_mode()
213  {
214  throw CUfileException("KvikIO not compiled with cuFile.h");
215  }
216 
217  [[nodiscard]] static bool get_nvfs_poll_mode()
218  {
219  throw CUfileException("KvikIO not compiled with cuFile.h");
220  }
221 
222  [[nodiscard]] static std::size_t get_nvfs_poll_thresh_size()
223  {
224  throw CUfileException("KvikIO not compiled with cuFile.h");
225  }
226 
227  static void set_nvfs_poll_mode(bool enable)
228  {
229  throw CUfileException("KvikIO not compiled with cuFile.h");
230  }
231 
232  static void set_nvfs_poll_thresh_size(std::size_t size_in_kb)
233  {
234  throw CUfileException("KvikIO not compiled with cuFile.h");
235  }
236 
237  [[nodiscard]] static std::vector<CUfileDriverControlFlags> get_nvfs_statusflags()
238  {
239  throw CUfileException("KvikIO not compiled with cuFile.h");
240  }
241 
242  [[nodiscard]] static std::size_t get_max_device_cache_size()
243  {
244  throw CUfileException("KvikIO not compiled with cuFile.h");
245  }
246 
247  static void set_max_device_cache_size(std::size_t size_in_kb)
248  {
249  throw CUfileException("KvikIO not compiled with cuFile.h");
250  }
251 
252  [[nodiscard]] static std::size_t get_per_buffer_cache_size()
253  {
254  throw CUfileException("KvikIO not compiled with cuFile.h");
255  }
256 
257  [[nodiscard]] static std::size_t get_max_pinned_memory_size()
258  {
259  throw CUfileException("KvikIO not compiled with cuFile.h");
260  }
261 
262  static void set_max_pinned_memory_size(std::size_t size_in_kb)
263  {
264  throw CUfileException("KvikIO not compiled with cuFile.h");
265  }
266 
267  [[nodiscard]] std::size_t get_max_batch_io_size()
268  {
269  throw CUfileException("KvikIO not compiled with cuFile.h");
270  }
271 };
272 #endif
273 
274 } // namespace kvikio