file_handle.hpp
1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2021-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #pragma once
6 
7 #include <sys/stat.h>
8 #include <sys/types.h>
9 
10 #include <atomic>
11 #include <cstddef>
12 #include <cstdlib>
13 
14 #include <kvikio/buffer.hpp>
15 #include <kvikio/compat_mode.hpp>
16 #include <kvikio/compat_mode_manager.hpp>
17 #include <kvikio/cufile/config.hpp>
18 #include <kvikio/defaults.hpp>
19 #include <kvikio/error.hpp>
20 #include <kvikio/file_utils.hpp>
21 #include <kvikio/shim/cufile.hpp>
22 #include <kvikio/shim/cufile_h_wrapper.hpp>
23 #include <kvikio/stream.hpp>
24 #include <kvikio/threadpool_wrapper.hpp>
25 #include <kvikio/utils.hpp>
26 
27 namespace kvikio {
28 
34 class FileHandle {
35  private:
36  // We use two file descriptors, one opened with the O_DIRECT flag and one without.
37  FileWrapper _file_direct_on{};
38  FileWrapper _file_direct_off{};
39  bool _initialized{false};
40  // The size of the underlying file, zero meaning unknown.
41  mutable std::atomic<std::size_t> _nbytes{0};
42  CUFileHandleWrapper _cufile_handle{};
43  CompatModeManager _compat_mode_manager;
44  std::string _file_path; // Reported to the monitors, see `Observation::source`.
45  friend class CompatModeManager;
46 
48  std::size_t read_impl(void* devPtr_base,
49  std::size_t size,
50  std::size_t file_offset,
51  std::size_t devPtr_offset,
52  bool sync_default_stream);
53 
55  std::size_t write_impl(void const* devPtr_base,
56  std::size_t size,
57  std::size_t file_offset,
58  std::size_t devPtr_offset,
59  bool sync_default_stream);
60  ThreadPool* _thread_pool{};
61 
62  public:
63  // 644 is a common setting of Unix file permissions: read and write for owner, read-only for group
64  // and others.
65  static constexpr mode_t m644 = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
66  FileHandle() noexcept = default;
67 
84  FileHandle(std::string const& file_path,
85  std::string const& flags = "r",
86  mode_t mode = m644,
87  CompatMode compat_mode = defaults::compat_mode());
88 
92  FileHandle(FileHandle const&) = delete;
93  FileHandle& operator=(FileHandle const&) = delete;
94  FileHandle(FileHandle&& o) noexcept;
95  FileHandle& operator=(FileHandle&& o) noexcept;
96  ~FileHandle() noexcept;
97 
103  [[nodiscard]] bool closed() const noexcept;
104 
108  void close() noexcept;
109 
118  [[nodiscard]] CUfileHandle_t handle();
119 
129  [[nodiscard]] int fd(bool o_direct = false) const noexcept;
130 
141  [[nodiscard]] int fd_open_flags(bool o_direct = false) const;
142 
150  [[nodiscard]] std::size_t nbytes() const;
151 
182  std::size_t read(void* devPtr_base,
183  std::size_t size,
184  std::size_t file_offset,
185  std::size_t devPtr_offset,
186  bool sync_default_stream = true);
187 
219  std::size_t write(void const* devPtr_base,
220  std::size_t size,
221  std::size_t file_offset,
222  std::size_t devPtr_offset,
223  bool sync_default_stream = true);
224 
259  std::future<std::size_t> pread(void* buf,
260  std::size_t size,
261  std::size_t file_offset = 0,
262  std::size_t task_size = defaults::task_size(),
263  std::size_t gds_threshold = defaults::gds_threshold(),
264  bool sync_default_stream = true,
265  ThreadPool* thread_pool = &defaults::thread_pool());
266 
301  std::future<std::size_t> pwrite(void const* buf,
302  std::size_t size,
303  std::size_t file_offset = 0,
304  std::size_t task_size = defaults::task_size(),
305  std::size_t gds_threshold = defaults::gds_threshold(),
306  bool sync_default_stream = true,
307  ThreadPool* thread_pool = &defaults::thread_pool());
308 
340  void read_async(void* devPtr_base,
341  std::size_t* size_p,
342  off_t* file_offset_p,
343  off_t* devPtr_offset_p,
344  ssize_t* bytes_read_p,
345  CUstream stream);
346 
369  [[nodiscard]] StreamFuture read_async(void* devPtr_base,
370  std::size_t size,
371  off_t file_offset = 0,
372  off_t devPtr_offset = 0,
373  CUstream stream = nullptr);
374 
407  void write_async(void* devPtr_base,
408  std::size_t* size_p,
409  off_t* file_offset_p,
410  off_t* devPtr_offset_p,
411  ssize_t* bytes_written_p,
412  CUstream stream);
413 
436  [[nodiscard]] StreamFuture write_async(void* devPtr_base,
437  std::size_t size,
438  off_t file_offset = 0,
439  off_t devPtr_offset = 0,
440  CUstream stream = nullptr);
441 
450 
459  bool is_direct_io_supported() const noexcept;
460 };
461 
462 } // namespace kvikio
Class that provides RAII for the cuFile handle.
Definition: file_utils.hpp:75
Store and manage the compatibility mode data associated with a FileHandle.
Handle of an open file registered with cufile.
Definition: file_handle.hpp:34
void close() noexcept
Deregister the file and close the two files.
int fd(bool o_direct=false) const noexcept
Get one of the file descriptors.
void read_async(void *devPtr_base, std::size_t *size_p, off_t *file_offset_p, off_t *devPtr_offset_p, ssize_t *bytes_read_p, CUstream stream)
Reads specified bytes from the file into the device memory asynchronously.
int fd_open_flags(bool o_direct=false) const
Get the flags of one of the file descriptors (see open(2))
std::size_t write(void const *devPtr_base, std::size_t size, std::size_t file_offset, std::size_t devPtr_offset, bool sync_default_stream=true)
Writes specified bytes from the device memory into the file.
CUfileHandle_t handle()
Get the underlying cuFile file handle.
const CompatModeManager & get_compat_mode_manager() const noexcept
Get the associated compatibility mode manager, which can be used to query the original requested comp...
FileHandle(std::string const &file_path, std::string const &flags="r", mode_t mode=m644, CompatMode compat_mode=defaults::compat_mode())
Construct a file handle from a file path.
bool closed() const noexcept
Whether the file is closed according to its initialization status.
std::future< std::size_t > pread(void *buf, std::size_t size, std::size_t file_offset=0, std::size_t task_size=defaults::task_size(), std::size_t gds_threshold=defaults::gds_threshold(), bool sync_default_stream=true, ThreadPool *thread_pool=&defaults::thread_pool())
Reads specified bytes from the file into the device or host memory in parallel.
std::future< std::size_t > pwrite(void const *buf, std::size_t size, std::size_t file_offset=0, std::size_t task_size=defaults::task_size(), std::size_t gds_threshold=defaults::gds_threshold(), bool sync_default_stream=true, ThreadPool *thread_pool=&defaults::thread_pool())
Writes specified bytes from device or host memory into the file in parallel.
void write_async(void *devPtr_base, std::size_t *size_p, off_t *file_offset_p, off_t *devPtr_offset_p, ssize_t *bytes_written_p, CUstream stream)
Writes specified bytes from the device memory into the file asynchronously.
std::size_t nbytes() const
Get the file size.
std::size_t read(void *devPtr_base, std::size_t size, std::size_t file_offset, std::size_t devPtr_offset, bool sync_default_stream=true)
Reads specified bytes from the file into the device memory.
bool is_direct_io_supported() const noexcept
Whether Direct I/O is supported on this file handle. This is determined by two factors:
FileHandle(FileHandle const &)=delete
FileHandle support move semantic but isn't copyable.
Class that provides RAII for file handling.
Definition: file_utils.hpp:16
Future of an asynchronous IO operation.
Definition: stream.hpp:35
Singleton class of default values used throughout KvikIO.
Definition: defaults.hpp:122
static CompatMode compat_mode()
Return whether the KvikIO library is running in compatibility mode or not.
KvikIO namespace.
Definition: batch.hpp:16
BS::thread_pool ThreadPool
Thread pool type used for parallel I/O operations.
CompatMode
I/O compatibility mode.
Definition: compat_mode.hpp:15