utils.hpp
1 /*
2  * 版权所有 (c) 2021-2025, NVIDIA CORPORATION.
3  *
4  * 根据 Apache 许可证 2.0 版(“许可证”)获得许可;
5  * 除非遵守许可证的规定,否则您不得使用此文件。
6  * 您可以在以下网址获取许可证副本:
7  *
8  * https://apache.ac.cn/licenses/LICENSE-2.0
9  *
10  * 除非适用法律要求或书面同意,否则根据许可证分发的软件按“原样”分发,
11  * 不附带任何明示或暗示的担保或条件。
12  * 请参阅许可证了解具体的语言许可和限制。
13  *
14  */
15 /*
16 #pragma once
17 
18 #include <chrono>
19 #include <cstring>
20 #include <future>
21 #include <optional>
22 #include <stdexcept>
23 #include <tuple>
24 #include <type_traits>
25 
26 #include <kvikio/error.hpp>
27 #include <kvikio/shim/cuda.hpp>
28 
29 namespace kvikio {
30 
31 // cuFile 将页面大小定义为 4 KiB
32 inline constexpr std::size_t page_size = 4096;
33 
34 [[nodiscard]] off_t convert_size2off(std::size_t x);
35 
36 [[nodiscard]] ssize_t convert_size2ssize(std::size_t x);
37 
38 [[nodiscard]] CUdeviceptr convert_void2deviceptr(void const* devPtr);
39 
43 /** 辅助函数,用于将值转换为 64 位带符号整数。*/
44 template <typename T, std::enable_if_t<std::is_integral_v<T>>* = nullptr>
45 [[nodiscard]] std::int64_t convert_to_64bit(T value)
46 {
47  if constexpr (std::numeric_limits<T>::max() > std::numeric_limits<std::int64_t>::max()) {
48  KVIKIO_EXPECT(value <= std::numeric_limits<std::int64_t>::max(),
49  "convert_to_64bit(x): x too large to fit std::int64_t",
50  std::overflow_error);
51  }
52  return std::int64_t(value);
53 }
58 /** 针对 `std::uint64_t` 的特化。*/
59 [[nodiscard]] inline std::uint64_t convert_to_64bit(std::uint64_t value) { return value; }
63 /** 针对浮点类型的特化。*/
64 template <typename T, std::enable_if_t<std::is_floating_point_v<T>>* = nullptr>
65 [[nodiscard]] double convert_to_64bit(T value)
66 {
67  return double(value);
68 }
77 /** 检查 ptr 是否指向主机内存(而不是设备内存)*/
78 #ifdef KVIKIO_CUDA_FOUND
79 bool is_host_memory(void const* ptr);
80 #else
81 constexpr bool is_host_memory(void const* ptr) { return true; }
82 #endif
89 /** 返回拥有该指针的设备。*/
90 [[nodiscard]] int get_device_ordinal_from_pointer(CUdeviceptr dev_ptr);
99 /** 给定设备序号,返回设备的主上下文。*/
100 [[nodiscard]] KVIKIO_EXPORT CUcontext get_primary_cuda_context(int ordinal);
107 /** 返回与给定设备指针关联的 CUDA 上下文(如果存在)。*/
108 [[nodiscard]] std::optional<CUcontext> get_context_associated_pointer(CUdeviceptr dev_ptr);
115 /** 检查当前的 CUDA 上下文是否可以访问给定的设备指针。*/
116 [[nodiscard]] bool current_context_can_access_pointer(CUdeviceptr dev_ptr);
133 /** 返回一个可以与给定设备指针一起使用的 CUDA 上下文。*/
134 [[nodiscard]] CUcontext get_context_from_pointer(void const* devPtr);
138 /** 在创建时压入 CUDA 上下文,在销毁时弹出它。*/
139 class PushAndPopContext {
140  private
141  CUcontext _ctx;
142 
143  public
144  PushAndPopContext(CUcontext ctx);
145  PushAndPopContext(PushAndPopContext const&) = delete;
146  PushAndPopContext& operator=(PushAndPopContext const&) = delete;
148  PushAndPopContext&& operator=(PushAndPopContext&&) = delete;
150 };
151 
152 // 查找 devPtr 所在内存分配的基址和偏移量
153 std::tuple<void*, std::size_t, std::size_t> get_alloc_info(void const* devPtr,
154  CUcontext* ctx = nullptr);
166 /** 在 future 对象中创建一个立即就绪的共享状态。*/
167 template <typename T>
168 std::future<std::decay_t<T>> make_ready_future(T&& t)
169 {
170  std::promise<std::decay_t<T>> p;
171  auto fut = p.get_future();
172  p.set_value(std::forward<T>(t));
173  return fut;
174 }
186 /** 检查 future 对象的状态。True 表示结果在 future 的共享状态中可用。*/
187 template <typename T>
188 bool is_future_done(T const& future)
189 {
190  KVIKIO_EXPECT(future.valid(),
191  "The future object does not refer to a valid shared state.",
192  std::invalid_argument);
193  return future.wait_for(std::chrono::seconds(0)) != std::future_status::timeout;
194 }
195 
在创建时压入 CUDA 上下文,在销毁时弹出它。
定义: utils.hpp:138
#define KVIKIO_EXPECT(...)
用于检查前置条件或条件的宏,当条件被违反时会抛出异常...
定义: error.hpp:216
KvikIO 命名空间。
定义: batch.hpp:27
CUcontext get_context_from_pointer(void const *devPtr)
返回一个可以与给定设备指针一起使用的 CUDA 上下文。
constexpr bool is_host_memory(void const *ptr)
检查 ptr 是否指向主机内存(而不是设备内存)
定义: utils.hpp:80
std::int64_t convert_to_64bit(T value)
辅助函数,用于将值转换为 64 位带符号整数。
定义: utils.hpp:44
bool current_context_can_access_pointer(CUdeviceptr dev_ptr)
检查当前的 CUDA 上下文是否可以访问给定的设备指针。
bool is_future_done(T const &future)
检查 future 对象的状态。True 表示结果在 future 的共享状态中可用。
定义: utils.hpp:187
KVIKIO_EXPORT CUcontext get_primary_cuda_context(int ordinal)
给定设备序号,返回设备的主上下文。
std::future< std::decay_t< T > > make_ready_future(T &&t)
在 future 对象中创建一个立即就绪的共享状态。
定义: utils.hpp:167
std::optional< CUcontext > get_context_associated_pointer(CUdeviceptr dev_ptr)
返回与给定设备指针关联的 CUDA 上下文(如果存在)。
int get_device_ordinal_from_pointer(CUdeviceptr dev_ptr)
返回拥有该指针的设备。