libkvikio  23.12.00
batch.hpp
1 /*
2  * Copyright (c) 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 <cstddef>
19 #include <ctime>
20 #include <utility>
21 #include <vector>
22 
23 #include <kvikio/error.hpp>
24 #include <kvikio/file_handle.hpp>
25 #include <kvikio/shim/cufile.hpp>
26 
27 namespace kvikio {
28 
32 struct BatchOp {
33  // The file handle of the file to read or write
34  FileHandle& file_handle;
35  // Base address of buffer in device memory (host memory not supported).
36  void* devPtr_base;
37  // Offset in the file to read from or write to.
38  off_t file_offset;
39  // Offset relative to the `devPtr_base` pointer to write into or read from.
40  off_t devPtr_offset;
41  // Size in bytes to read or write.
42  size_t size;
43  // The operation type: CUFILE_READ or CUFILE_WRITE.
44  CUfileOpcode_t opcode;
45 };
46 
47 #ifdef KVIKIO_CUFILE_BATCH_API_FOUND
48 
62 class BatchHandle {
63  private:
64  bool _initialized{false};
65  int _max_num_events{};
66  CUfileBatchHandle_t _handle{};
67 
68  public:
69  BatchHandle() noexcept = default;
70 
76  BatchHandle(int max_num_events) : _initialized{true}, _max_num_events{max_num_events}
77  {
78  CUFILE_TRY(cuFileAPI::instance().BatchIOSetUp(&_handle, max_num_events));
79  }
80 
84  BatchHandle(const BatchHandle&) = delete;
85  BatchHandle& operator=(BatchHandle const&) = delete;
86  BatchHandle(BatchHandle&& o) noexcept
87  : _initialized{std::exchange(o._initialized, false)},
88  _max_num_events{std::exchange(o._max_num_events, 0)}
89  {
90  _handle = std::exchange(o._handle, CUfileBatchHandle_t{});
91  }
92  ~BatchHandle() noexcept { close(); }
93 
94  [[nodiscard]] bool closed() const noexcept { return !_initialized; }
95 
99  void close() noexcept
100  {
101  if (closed()) { return; }
102  _initialized = false;
103 
104  cuFileAPI::instance().BatchIODestroy(_handle);
105  }
106 
113  void submit(const std::vector<BatchOp>& operations)
114  {
115  if (convert_size2ssize(operations.size()) > _max_num_events) {
116  throw CUfileException("Cannot submit more than the max_num_events)");
117  }
118  std::vector<CUfileIOParams_t> io_batch_params;
119  io_batch_params.reserve(operations.size());
120  for (const auto& op : operations) {
121  if (op.file_handle.is_compat_mode_on()) {
122  throw CUfileException("Cannot submit a FileHandle opened in compatibility mode");
123  }
124 
125  io_batch_params.push_back(CUfileIOParams_t{.mode = CUFILE_BATCH,
126  .u = {.batch = {.devPtr_base = op.devPtr_base,
127  .file_offset = op.file_offset,
128  .devPtr_offset = op.devPtr_offset,
129  .size = op.size}},
130  .fh = op.file_handle.handle(),
131  .opcode = op.opcode,
132  .cookie = nullptr});
133  }
134 
135  CUFILE_TRY(cuFileAPI::instance().BatchIOSubmit(
136  _handle, io_batch_params.size(), io_batch_params.data(), 0));
137  }
138 
149  std::vector<CUfileIOEvents_t> status(unsigned min_nr,
150  unsigned max_nr,
151  struct timespec* timeout = nullptr)
152  {
153  std::vector<CUfileIOEvents_t> ret;
154  ret.resize(_max_num_events);
155  CUFILE_TRY(cuFileAPI::instance().BatchIOGetStatus(_handle, min_nr, &max_nr, &ret[0], timeout));
156  ret.resize(max_nr);
157  return ret;
158  }
159 
160  void cancel() { CUFILE_TRY(cuFileAPI::instance().BatchIOCancel(_handle)); }
161 };
162 
163 #else
164 
165 class BatchHandle {
166  public:
167  BatchHandle() noexcept = default;
168 
169  BatchHandle(int max_num_events)
170  {
171  throw CUfileException("BatchHandle requires cuFile's batch API, please build with CUDA v12.1+");
172  }
173 
174  [[nodiscard]] bool closed() const noexcept { return true; }
175 
176  void close() noexcept {}
177 
178  void submit(const std::vector<BatchOp>& operations) {}
179 
180  std::vector<CUfileIOEvents_t> status(unsigned min_nr,
181  unsigned max_nr,
182  struct timespec* timeout = nullptr)
183  {
184  return std::vector<CUfileIOEvents_t>{};
185  }
186  void cancel() {}
187 };
188 
189 #endif
190 
191 } // namespace kvikio
Handle of an open file registered with cufile.
IO operation used when submitting batches.
Definition: batch.hpp:32