Skip to content

Commit c9209aa

Browse files
authored
Python bindings to cuFileDriverOpen() and cuFileDriverClose() (#514)
Changes: - Adding Python bindings to `cuFileDriverOpen()` and `cuFileDriverClose()`. - We now [only open the cufile driver explicitly](#160) in CUDA versions older than v12.2. - Introducing `kvikio.cufile_driver.initialize()`, which open the cuFile driver and close it again at module exit. - Let CI fail if KvikIO wasn't built with cuFile support. * Except on cuda11.8+arm64; cuFile didn't support arm until cuda v12.4. - Some refactor and clean up! Authors: - Mads R. B. Kristensen (https://github.com/madsbk) Approvers: - Lawrence Mitchell (https://github.com/wence-) - Vyas Ramasubramani (https://github.com/vyasr) URL: #514
1 parent fc56da6 commit c9209aa

17 files changed

Lines changed: 178 additions & 38 deletions

File tree

ci/run_pytests.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,9 @@ set -euo pipefail
66
# Support invoking run_pytests.sh outside the script directory
77
cd "$(dirname "$(realpath "${BASH_SOURCE[0]}")")"/../python/kvikio
88

9-
pytest --cache-clear --verbose "$@" tests
9+
# If running CUDA 11.8 on arm64, we skip tests marked "cufile" since
10+
# cuFile didn't support arm until 12.4
11+
[[ "${CUDA_VERSION}" == "11.8.0" && "${RUNNER_ARCH}" == "ARM64" ]] \
12+
&& PYTEST_MARK=( -m 'not cufile' ) || PYTEST_MARK=()
13+
14+
pytest --cache-clear --verbose "${PYTEST_MARK[@]}" "$@" tests

ci/test_wheel.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,9 @@ RAPIDS_PY_WHEEL_NAME="kvikio_${RAPIDS_PY_CUDA_SUFFIX}" rapids-download-wheels-fr
99

1010
python -m pip install "$(echo ${WHEELHOUSE}/kvikio_${RAPIDS_PY_CUDA_SUFFIX}*.whl)[test]"
1111

12-
python -m pytest ./python/kvikio/tests
12+
# If running CUDA 11.8 on arm64, we skip tests marked "cufile" since
13+
# cuFile didn't support arm until 12.4
14+
[[ "${CUDA_VERSION}" == "11.8.0" && "${RUNNER_ARCH}" == "ARM64" ]] \
15+
&& PYTEST_MARK=( -m 'not cufile' ) || PYTEST_MARK=()
16+
17+
python -m pytest --cache-clear --verbose "${PYTEST_MARK[@]}" ./python/kvikio/tests

cpp/examples/basic_io.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121

2222
#include <kvikio/batch.hpp>
2323
#include <kvikio/buffer.hpp>
24+
#include <kvikio/cufile/driver.hpp>
2425
#include <kvikio/defaults.hpp>
25-
#include <kvikio/driver.hpp>
2626
#include <kvikio/error.hpp>
2727
#include <kvikio/file_handle.hpp>
2828

cpp/examples/basic_no_cuda.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919

2020
#include <kvikio/batch.hpp>
2121
#include <kvikio/buffer.hpp>
22+
#include <kvikio/cufile/driver.hpp>
2223
#include <kvikio/defaults.hpp>
23-
#include <kvikio/driver.hpp>
2424
#include <kvikio/error.hpp>
2525
#include <kvikio/file_handle.hpp>
2626

cpp/examples/downstream/downstream_example.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,23 @@
1+
/*
2+
* Copyright (c) 2022-2024, 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+
117
#include <iostream>
218

19+
#include <kvikio/cufile/driver.hpp>
320
#include <kvikio/defaults.hpp>
4-
#include <kvikio/driver.hpp>
521

622
using namespace std;
723

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021-2023, NVIDIA CORPORATION.
2+
* Copyright (c) 2021-2024, NVIDIA CORPORATION.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -45,7 +45,7 @@ inline void set_driver_flag(unsigned int& prop, unsigned int flag, bool val) noe
4545
class DriverInitializer {
4646
// Optional, if not used cuFiles opens the driver automatically
4747
public:
48-
DriverInitializer() { CUFILE_TRY(cuFileAPI::instance().DriverOpen()); }
48+
DriverInitializer() { cuFileAPI::instance().driver_open(); }
4949

5050
DriverInitializer(DriverInitializer const&) = delete;
5151
DriverInitializer& operator=(DriverInitializer const&) = delete;
@@ -55,7 +55,7 @@ class DriverInitializer {
5555
~DriverInitializer()
5656
{
5757
try {
58-
CUFILE_TRY(cuFileAPI::instance().DriverClose());
58+
cuFileAPI::instance().driver_close();
5959
} catch (const CUfileException& e) {
6060
std::cerr << "Unable to close GDS file driver: ";
6161
std::cerr << e.what();

cpp/include/kvikio/file_handle.hpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,12 @@
2222

2323
#include <cstddef>
2424
#include <cstdlib>
25-
#include <iostream>
26-
#include <numeric>
27-
#include <optional>
2825
#include <stdexcept>
2926
#include <system_error>
3027
#include <utility>
3128

3229
#include <kvikio/buffer.hpp>
33-
#include <kvikio/cufile_config.hpp>
30+
#include <kvikio/cufile/config.hpp>
3431
#include <kvikio/defaults.hpp>
3532
#include <kvikio/error.hpp>
3633
#include <kvikio/parallel_operation.hpp>

cpp/include/kvikio/shim/cufile.hpp

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
#pragma once
1717

1818
#include <stdexcept>
19+
#include <string>
1920

20-
#include <iostream>
2121
#include <kvikio/shim/cufile_h_wrapper.hpp>
2222
#include <kvikio/shim/utils.hpp>
2323

@@ -38,8 +38,6 @@ class cuFileAPI {
3838
decltype(cuFileWrite)* Write{nullptr};
3939
decltype(cuFileBufRegister)* BufRegister{nullptr};
4040
decltype(cuFileBufDeregister)* BufDeregister{nullptr};
41-
decltype(cuFileDriverOpen)* DriverOpen{nullptr};
42-
decltype(cuFileDriverClose)* DriverClose{nullptr};
4341
decltype(cuFileDriverGetProperties)* DriverGetProperties{nullptr};
4442
decltype(cuFileDriverSetPollMode)* DriverSetPollMode{nullptr};
4543
decltype(cuFileDriverSetMaxCacheSize)* DriverSetMaxCacheSize{nullptr};
@@ -54,6 +52,12 @@ class cuFileAPI {
5452
decltype(cuFileStreamRegister)* StreamRegister{nullptr};
5553
decltype(cuFileStreamDeregister)* StreamDeregister{nullptr};
5654

55+
private:
56+
// Don't call driver open and close directly, use `.driver_open()` and `.driver_close()`.
57+
decltype(cuFileDriverOpen)* DriverOpen{nullptr};
58+
decltype(cuFileDriverClose)* DriverClose{nullptr};
59+
60+
public:
5761
bool stream_available = false;
5862

5963
private:
@@ -105,25 +109,25 @@ class cuFileAPI {
105109
}
106110
#endif
107111

108-
// cuFile is supposed to open and close the driver automatically but because of a bug in
109-
// CUDA 11.8, it sometimes segfault. See <https://github.com/rapidsai/kvikio/issues/159>.
110-
CUfileError_t const error = DriverOpen();
111-
if (error.err != CU_FILE_SUCCESS) {
112-
throw std::runtime_error(std::string{"cuFile error at: "} + __FILE__ + ":" +
113-
KVIKIO_STRINGIFY(__LINE__) + ": " +
114-
cufileop_status_error(error.err));
115-
}
112+
// cuFile is supposed to open and close the driver automatically but
113+
// because of a bug in cuFile v1.4 (CUDA v11.8) it sometimes segfaults:
114+
// <https://github.com/rapidsai/kvikio/issues/159>.
115+
// We use the stream API as a version indicator of cuFile since it was introduced
116+
// in cuFile v1.7 (CUDA v12.2).
117+
if (!stream_available) { driver_open(); }
116118
}
119+
120+
// Notice, we have to close the driver at program exit (if we opened it) even though we are
121+
// not allowed to call CUDA after main[1]. This is because, cuFile will segfault if the
122+
// driver isn't closed on program exit i.e. we are doomed if we do, doomed if we don't, but
123+
// this seems to be the lesser of two evils.
124+
// [1] <https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#initialization>
117125
~cuFileAPI()
118126
{
119-
CUfileError_t const error = DriverClose();
120-
if (error.err != CU_FILE_SUCCESS) {
121-
std::cerr << "Unable to close GDS file driver: " << cufileop_status_error(error.err)
122-
<< std::endl;
123-
}
127+
if (!stream_available) { driver_close(); }
124128
}
125129
#else
126-
cuFileAPI() { throw std::runtime_error(CUFILE_ERRSTR(0)); }
130+
cuFileAPI() { throw std::runtime_error("KvikIO not compiled with cuFile.h"); }
127131
#endif
128132

129133
public:
@@ -137,6 +141,33 @@ class cuFileAPI {
137141
static cuFileAPI _instance;
138142
return _instance;
139143
}
144+
145+
/**
146+
* @brief Open the cuFile driver
147+
*
148+
* cuFile allows multiple calls to `cufileDriverOpen()`, only the first call opens
149+
* the driver, but every call should have a matching call to `cufileDriverClose()`.
150+
*/
151+
void driver_open()
152+
{
153+
CUfileError_t const error = DriverOpen();
154+
if (error.err != CU_FILE_SUCCESS) {
155+
throw std::runtime_error(std::string{"Unable to open GDS file driver: "} +
156+
cufileop_status_error(error.err));
157+
}
158+
}
159+
160+
/**
161+
* @brief Close the cuFile driver
162+
*/
163+
void driver_close()
164+
{
165+
CUfileError_t const error = DriverClose();
166+
if (error.err != CU_FILE_SUCCESS) {
167+
throw std::runtime_error(std::string{"Unable to close GDS file driver: "} +
168+
cufileop_status_error(error.err));
169+
}
170+
}
140171
};
141172

142173
/**

cpp/include/kvikio/stream.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
#pragma once
1717

1818
#include <sys/types.h>
19-
#include <algorithm>
2019
#include <cstdlib>
20+
#include <iostream>
2121
#include <kvikio/error.hpp>
2222
#include <kvikio/shim/cuda.hpp>
2323
#include <kvikio/shim/cufile.hpp>

0 commit comments

Comments
 (0)