Skip to content

Commit

Permalink
is_batch_api_available() and is_stream_api_available()
Browse files Browse the repository at this point in the history
  • Loading branch information
madsbk committed Dec 4, 2024
1 parent 5cf410c commit 9782754
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 39 deletions.
2 changes: 1 addition & 1 deletion cpp/examples/basic_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ int main()
cout << "Parallel POSIX read (" << kvikio::defaults::thread_pool_nthreads()
<< " threads): " << read << endl;
}
if (kvikio::is_batch_and_stream_available() && !kvikio::defaults::is_compat_mode_preferred()) {
if (kvikio::is_batch_api_available() && !kvikio::defaults::is_compat_mode_preferred()) {
std::cout << std::endl;
Timer timer;
// Here we use the batch API to read "/tmp/test-file" into `b_dev` by
Expand Down
29 changes: 13 additions & 16 deletions cpp/include/kvikio/file_handle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,23 +62,20 @@ class FileHandle {
*/
bool is_compat_mode_preferred_for_async(CompatMode requested_compat_mode)
{
if (!defaults::is_compat_mode_preferred(requested_compat_mode)) {
if (!is_batch_and_stream_available()) {
if (requested_compat_mode == CompatMode::AUTO) { return true; }
throw std::runtime_error("Missing cuFile batch or stream library symbol.");
}

// When checking for availability, we also check if cuFile's config file exist. This is
// because even when the stream API is available, it doesn't work if no config file exist.
if (config_path().empty()) {
if (requested_compat_mode == CompatMode::AUTO) { return true; }
throw std::runtime_error("Missing cuFile configuration file.");
}

return false;
if (defaults::is_compat_mode_preferred(requested_compat_mode)) { return true; }

if (!is_stream_api_available()) {
if (requested_compat_mode == CompatMode::AUTO) { return true; }
throw std::runtime_error("Missing the cuFile stream api.");
}

return true;
// When checking for availability, we also check if cuFile's config file exist. This is
// because even when the stream API is available, it doesn't work if no config file exist.
if (config_path().empty()) {
if (requested_compat_mode == CompatMode::AUTO) { return true; }
throw std::runtime_error("Missing cuFile configuration file.");
}
return false;
}

public:
Expand Down Expand Up @@ -670,7 +667,7 @@ class FileHandle {
*/
[[nodiscard]] bool is_compat_mode_preferred_for_async() const noexcept
{
static bool is_extra_symbol_available = is_batch_and_stream_available();
static bool is_extra_symbol_available = is_stream_api_available();
static bool is_config_path_empty = config_path().empty();
return is_compat_mode_preferred() || !is_extra_symbol_available || is_config_path_empty;
}
Expand Down
59 changes: 37 additions & 22 deletions cpp/include/kvikio/shim/cufile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ class cuFileAPI {
decltype(cuFileGetVersion)* GetVersion{nullptr};

public:
bool stream_available = false;
int version{0};

private:
Expand Down Expand Up @@ -119,20 +118,12 @@ class cuFileAPI {
get_symbol(WriteAsync, lib, KVIKIO_STRINGIFY(cuFileWriteAsync));
get_symbol(StreamRegister, lib, KVIKIO_STRINGIFY(cuFileStreamRegister));
get_symbol(StreamDeregister, lib, KVIKIO_STRINGIFY(cuFileStreamDeregister));
try {
void* s{};
get_symbol(s, lib, "cuFileReadAsync");
stream_available = true;
} catch (const std::runtime_error&) {
}
#endif

// cuFile is supposed to open and close the driver automatically but
// because of a bug in cuFile v1.4 (CUDA v11.8) it sometimes segfaults:
// <https://github.com/rapidsai/kvikio/issues/159>.
// We use the stream API as a version indicator of cuFile since it was introduced
// in cuFile v1.7 (CUDA v12.2).
if (!stream_available) { driver_open(); }
if (version < 1050) { driver_open(); }
}

// Notice, we have to close the driver at program exit (if we opened it) even though we are
Expand All @@ -142,7 +133,7 @@ class cuFileAPI {
// [1] <https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#initialization>
~cuFileAPI()
{
if (!stream_available) { driver_close(); }
if (version < 1050) { driver_close(); }
}
#else
cuFileAPI() { throw std::runtime_error("KvikIO not compiled with cuFile.h"); }
Expand Down Expand Up @@ -223,25 +214,49 @@ inline bool is_cufile_available()
}

/**
* @brief Check if cuFile's batch and stream API is available
* @brief Get cufile version (or zero if older than v1.8).
*
* Technically, the batch API is available in CUDA 12.1 but since there is no good
* way to check CUDA version using the driver API, we check for the existing of the
* `cuFileReadAsync` symbol, which is defined in CUDA 12.2+.
* The version is returned as (1000 major + 10 minor). E.g., cufile v1.8.0 would
* be represented by 1080.
*
* @return The boolean answer
* Notice, this is not the version of the CUDA toolkit. cufile is part of the
* toolkit but follows its own version scheme.
*
* @return The version (1000 major + 10 minor).
*/
#if defined(KVIKIO_CUFILE_STREAM_API_FOUND) && defined(KVIKIO_CUFILE_STREAM_API_FOUND)
inline bool is_batch_and_stream_available() noexcept
#ifdef KVIKIO_CUFILE_FOUND
inline int cufile_version()
{
try {
return is_cufile_available() && cuFileAPI::instance().stream_available;
} catch (const std::runtime_error&) {
return false;
return cuFileAPI::instance().version;
} catch (std::runtime_error const&) {
return 0;
}
}
#else
constexpr bool is_batch_and_stream_available() { return false; }
constexpr bool cufile_version() { return 0; }
#endif

/**
* @brief Check if cuFile's batch API is available.
*
* Since `cuFileGetVersion()` first became available in cufile v1.8 (CTK v12.3),
* this function returns false for versions older than v1.8 even though the batch
* API became available in v1.6.
*
* @return The boolean answer
*/
inline bool is_batch_api_available() noexcept { return cufile_version() > 1060; }

/**
* @brief Check if cuFile's stream (async) API is available.
*
* Since `cuFileGetVersion()` first became available in cufile v1.8 (CTK v12.3),
* this function returns false for versions older than v1.8 even though the stream
* API became available in v1.7.
*
* @return The boolean answer
*/
inline bool is_stream_api_available() noexcept { return cufile_version() > 1070; }

} // namespace kvikio

0 comments on commit 9782754

Please sign in to comment.