From 150c82f1760d31bb220dec5587d1e493cc82c8b2 Mon Sep 17 00:00:00 2001 From: Basit Ayantunde Date: Fri, 21 Aug 2026 18:01:01 +0100 Subject: [PATCH 1/3] Use a Meyers singleton for the cuDF context --- cpp/benchmarks/fixture/nvbench_fixture.hpp | 2 +- cpp/include/cudf/context.hpp | 28 +-- cpp/include/cudf_test/testing_main.hpp | 6 +- .../benchmarks/streaming/ndsh/bench_read.cpp | 2 - .../benchmarks/streaming/ndsh/q01.cpp | 2 - .../benchmarks/streaming/ndsh/q03.cpp | 2 - .../benchmarks/streaming/ndsh/q04.cpp | 2 - .../benchmarks/streaming/ndsh/q09.cpp | 2 - .../benchmarks/streaming/ndsh/q21.cpp | 1 - cpp/src/runtime/context.cpp | 200 ++++++++---------- cpp/src/runtime/context.hpp | 12 +- cpp/tests/utilities_tests/context_tests.cpp | 48 +---- 12 files changed, 121 insertions(+), 186 deletions(-) diff --git a/cpp/benchmarks/fixture/nvbench_fixture.hpp b/cpp/benchmarks/fixture/nvbench_fixture.hpp index 73f70efaba27..f07965a5bfd5 100644 --- a/cpp/benchmarks/fixture/nvbench_fixture.hpp +++ b/cpp/benchmarks/fixture/nvbench_fixture.hpp @@ -83,7 +83,7 @@ struct nvbench_base_fixture { nvbench_base_fixture(int argc, char const* const* argv) { - cudf::initialize(cudf::init_flags::ALL); + cudf::detail::initialize(cudf::init_flags::ALL); for (int i = 1; i < argc - 1; ++i) { std::string arg = argv[i]; diff --git a/cpp/include/cudf/context.hpp b/cpp/include/cudf/context.hpp index fa91d1eafd3c..5ec8b975221b 100644 --- a/cpp/include/cudf/context.hpp +++ b/cpp/include/cudf/context.hpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -18,12 +18,10 @@ enum class init_flags : std::uint32_t { NONE = 0, /// @brief Load the nvCOMP library during initialization LOAD_NVCOMP = 1 << 0, - /// @brief Initialize the JIT program cache during initialization - INIT_JIT_CACHE = 1 << 1, - /// @brief Pre-load the JIT program cache from disk during initialization - DEFAULT = INIT_JIT_CACHE, + /// @brief Default initialization steps + DEFAULT = LOAD_NVCOMP, /// @brief All initialization steps (default behavior) - ALL = LOAD_NVCOMP | INIT_JIT_CACHE + ALL = LOAD_NVCOMP }; /// @brief Bitwise OR operator for init_flags @@ -66,19 +64,15 @@ constexpr bool has_flag(init_flags flags, init_flags flag) noexcept return (flags | flag) == flags; } -/// @brief Initialize the cudf global context -/// @param flags Optional flags to control which initialization steps to perform. -/// Can be called multiple times to initialize additional components. If all selected -/// steps are already performed, the call has no effect. +namespace detail { + +/// @brief Ensure the cudf global context is initialized. Only the first call to this function will have an effect, subsequent calls are no-ops. +/// This function is thread-safe and can be called from multiple threads concurrently. +/// It is intended for library advanced users who need to explicitly control the initialization order of the cuDF context. Most users should not need to call this function directly, as the context is automatically initialized when needed. +/// @param flags Optional flags controlling which components to initialize void initialize(init_flags flags = init_flags::DEFAULT); -/// @brief Destroy the cudf global context, resetting it to an uninitialized state. This is -/// primarily intended for testing purposes, allowing for re-initialization of the context after -/// teardown. -/// @warning This is not intended for general use and may lead to undefined behavior if used -/// improperly. The caller must ensure that no threads are concurrently accessing the context during -/// teardown and that only one thread calls teardown at a time. -void teardown(); +} // namespace detail /** * @brief Enable or disable the JIT program cache diff --git a/cpp/include/cudf_test/testing_main.hpp b/cpp/include/cudf_test/testing_main.hpp index 69a66ca568db..f2221bc958ce 100644 --- a/cpp/include/cudf_test/testing_main.hpp +++ b/cpp/include/cudf_test/testing_main.hpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -252,7 +252,7 @@ inline void init_cudf_test(int argc, char** argv, cudf::test::config const& conf #define CUDF_TEST_PROGRAM_MAIN() \ int main(int argc, char** argv) \ { \ - cudf::initialize(); \ + cudf::detail::initialize(); \ ::testing::InitGoogleTest(&argc, argv); \ init_cudf_test(argc, argv); \ if (std::getenv("GTEST_CUDF_MEMORY_PEAK")) { \ @@ -260,12 +260,10 @@ inline void init_cudf_test(int argc, char** argv, cudf::test::config const& conf cudf::set_current_device_resource(mr); \ auto rc = RUN_ALL_TESTS(); \ std::cout << "Peak memory usage " << mr.get_bytes_counter().peak << " bytes" << std::endl; \ - cudf::teardown(); \ rmm::mr::reset_current_device_resource(); \ return rc; \ } else { \ auto rc = RUN_ALL_TESTS(); \ - cudf::teardown(); \ rmm::mr::reset_current_device_resource(); \ return rc; \ } \ diff --git a/cpp/libcudf_streaming/benchmarks/streaming/ndsh/bench_read.cpp b/cpp/libcudf_streaming/benchmarks/streaming/ndsh/bench_read.cpp index 6614fc0aaf5b..ae1a765c10e1 100644 --- a/cpp/libcudf_streaming/benchmarks/streaming/ndsh/bench_read.cpp +++ b/cpp/libcudf_streaming/benchmarks/streaming/ndsh/bench_read.cpp @@ -324,8 +324,6 @@ int main(int argc, char** argv) { rapidsmpf::ndsh::FinalizeMPI finalize{}; CUDF_CUDA_TRY(cudaFree(nullptr)); - // work around https://github.com/NVIDIA/cudf/issues/20849 - cudf::initialize(); auto mr = rmm::mr::cuda_async_memory_resource{}; auto arguments = parse_arguments(argc, argv); rapidsmpf::ndsh::ProgramOptions ctx_arguments{ diff --git a/cpp/libcudf_streaming/benchmarks/streaming/ndsh/q01.cpp b/cpp/libcudf_streaming/benchmarks/streaming/ndsh/q01.cpp index 9c259404fa20..f3d9dfdb3814 100644 --- a/cpp/libcudf_streaming/benchmarks/streaming/ndsh/q01.cpp +++ b/cpp/libcudf_streaming/benchmarks/streaming/ndsh/q01.cpp @@ -264,8 +264,6 @@ int main(int argc, char** argv) { rapidsmpf::ndsh::FinalizeMPI finalize{}; CUDF_CUDA_TRY(cudaFree(nullptr)); - // work around https://github.com/NVIDIA/cudf/issues/20849 - cudf::initialize(); auto mr = rmm::mr::cuda_async_memory_resource{}; auto arguments = rapidsmpf::ndsh::parse_arguments(argc, argv); auto [ctx, comm] = rapidsmpf::ndsh::create_context(arguments, std::move(mr)); diff --git a/cpp/libcudf_streaming/benchmarks/streaming/ndsh/q03.cpp b/cpp/libcudf_streaming/benchmarks/streaming/ndsh/q03.cpp index 783014e8ce0e..a756bb6706d3 100644 --- a/cpp/libcudf_streaming/benchmarks/streaming/ndsh/q03.cpp +++ b/cpp/libcudf_streaming/benchmarks/streaming/ndsh/q03.cpp @@ -340,8 +340,6 @@ int main(int argc, char** argv) { rapidsmpf::ndsh::FinalizeMPI finalize{}; CUDF_CUDA_TRY(cudaFree(nullptr)); - // work around https://github.com/NVIDIA/cudf/issues/20849 - cudf::initialize(); auto mr = rmm::mr::cuda_async_memory_resource{}; auto arguments = rapidsmpf::ndsh::parse_arguments(argc, argv); auto [ctx, comm] = rapidsmpf::ndsh::create_context(arguments, std::move(mr)); diff --git a/cpp/libcudf_streaming/benchmarks/streaming/ndsh/q04.cpp b/cpp/libcudf_streaming/benchmarks/streaming/ndsh/q04.cpp index 23d543291de9..8760044a7957 100644 --- a/cpp/libcudf_streaming/benchmarks/streaming/ndsh/q04.cpp +++ b/cpp/libcudf_streaming/benchmarks/streaming/ndsh/q04.cpp @@ -238,8 +238,6 @@ int main(int argc, char** argv) { rapidsmpf::ndsh::FinalizeMPI finalize{}; CUDF_CUDA_TRY(cudaFree(nullptr)); - // work around https://github.com/NVIDIA/cudf/issues/20849 - cudf::initialize(); auto mr = rmm::mr::cuda_async_memory_resource{}; auto arguments = rapidsmpf::ndsh::parse_arguments(argc, argv); auto [ctx, comm] = rapidsmpf::ndsh::create_context(arguments, std::move(mr)); diff --git a/cpp/libcudf_streaming/benchmarks/streaming/ndsh/q09.cpp b/cpp/libcudf_streaming/benchmarks/streaming/ndsh/q09.cpp index 630c1af23c07..7c138f0920bb 100644 --- a/cpp/libcudf_streaming/benchmarks/streaming/ndsh/q09.cpp +++ b/cpp/libcudf_streaming/benchmarks/streaming/ndsh/q09.cpp @@ -319,8 +319,6 @@ int main(int argc, char** argv) { rapidsmpf::ndsh::FinalizeMPI finalize{}; CUDF_CUDA_TRY(cudaFree(nullptr)); - // work around https://github.com/NVIDIA/cudf/issues/20849 - cudf::initialize(); auto mr = rmm::mr::cuda_async_memory_resource{}; auto arguments = rapidsmpf::ndsh::parse_arguments(argc, argv); auto [ctx, comm] = rapidsmpf::ndsh::create_context(arguments, std::move(mr)); diff --git a/cpp/libcudf_streaming/benchmarks/streaming/ndsh/q21.cpp b/cpp/libcudf_streaming/benchmarks/streaming/ndsh/q21.cpp index 7eaa08229187..ca5c13999e41 100644 --- a/cpp/libcudf_streaming/benchmarks/streaming/ndsh/q21.cpp +++ b/cpp/libcudf_streaming/benchmarks/streaming/ndsh/q21.cpp @@ -489,7 +489,6 @@ int main(int argc, char** argv) { rapidsmpf::ndsh::FinalizeMPI finalize{}; CUDF_CUDA_TRY(cudaFree(nullptr)); - cudf::initialize(); auto mr = rmm::mr::cuda_async_memory_resource{}; auto arguments = rapidsmpf::ndsh::parse_arguments(argc, argv); auto [ctx, comm] = rapidsmpf::ndsh::create_context(arguments, std::move(mr)); diff --git a/cpp/src/runtime/context.cpp b/cpp/src/runtime/context.cpp index 7c4ffaf192ec..8af09f068da4 100644 --- a/cpp/src/runtime/context.cpp +++ b/cpp/src/runtime/context.cpp @@ -9,6 +9,7 @@ #include "jit/cache.hpp" #include +#include #include #include @@ -57,42 +58,47 @@ context::context(context_config cfg, init_flags flags) _nvrtc_version{0}, _nvjitlink_version{0} { + rtcx::initialize(); + initialize_jit(); initialize_components(flags); } -void context::ensure_nvcomp_loaded() { io::detail::nvcomp::load_nvcomp_library(); } +void context::preload_nvcomp() +{ + CUDF_FUNC_RANGE(); + + io::detail::nvcomp::load_nvcomp_library(); +} -void context::ensure_jit_cache_initialized() +void context::initialize_jit() { - std::call_once(_jit_cache_init_flag, [&]() { - // make sure the required directories exist - std::filesystem::create_directories(_config.rtcx_cache_dir); - std::filesystem::create_directories(_config.jit_bundle_dir); - std::filesystem::create_directories(_config.jit_pch_dir); - std::filesystem::create_directories(_config.jit_tmp_dir); - - rtcx::initialize(); - - _nvrtc_version = rtcx::nvrtc_version(); - _nvjitlink_version = rtcx::nvjitlink_version(); - - auto limits = rtcx::cache_limits{.num_mem_blobs = _config.kernel_cache_limit_process, - .num_mem_libraries = _config.kernel_cache_limit_process}; - - _rtcx_cache = std::make_unique(_config.rtcx_cache_dir, - _config.jit_tmp_dir, - limits, - bool{_config.preload_jit_cache}, - bool{_config.disable_jit_cache}); - - if (_config.clear_jit_cache) { - _rtcx_cache->clear_memory_store(); - _rtcx_cache->clear_disk_store(); - } + CUDF_FUNC_RANGE(); + + // make sure the required directories exist + std::filesystem::create_directories(_config.rtcx_cache_dir); + std::filesystem::create_directories(_config.jit_bundle_dir); + std::filesystem::create_directories(_config.jit_pch_dir); + std::filesystem::create_directories(_config.jit_tmp_dir); + + _nvrtc_version = rtcx::nvrtc_version(); + _nvjitlink_version = rtcx::nvjitlink_version(); + + auto limits = rtcx::cache_limits{.num_mem_blobs = _config.kernel_cache_limit_process, + .num_mem_libraries = _config.kernel_cache_limit_process}; - // note that jit_bundle depends on rtcx_cache, so we ensure rtcx_cache is initialized first. - _jit_bundle = std::make_unique(_config.jit_bundle_dir, *_rtcx_cache); - }); + _rtcx_cache = std::make_unique(_config.rtcx_cache_dir, + _config.jit_tmp_dir, + limits, + bool{_config.preload_jit_cache}, + bool{_config.disable_jit_cache}); + + if (_config.clear_jit_cache) { + _rtcx_cache->clear_memory_store(); + _rtcx_cache->clear_disk_store(); + } + + // note that jit_bundle depends on rtcx_cache, so we ensure rtcx_cache is initialized first. + _jit_bundle = std::make_unique(_config.jit_bundle_dir, *_rtcx_cache); } context::~context() @@ -102,17 +108,9 @@ context::~context() rtcx::teardown(); } -rtcx::cache_t& context::rtcx_cache() -{ - ensure_jit_cache_initialized(); - return *_rtcx_cache; -} +rtcx::cache_t& context::rtcx_cache() { return *_rtcx_cache; } -jit_bundle_t& context::jit_bundle() -{ - ensure_jit_cache_initialized(); - return *_jit_bundle; -} +jit_bundle_t& context::jit_bundle() { return *_jit_bundle; } bool context::dump_codegen() const { return _config.dump_codegen; } @@ -133,11 +131,12 @@ std::optional context::nvjitlink_version() const { return _nvjitlink_ve void context::initialize_components(init_flags flags) { - if (has_flag(flags, init_flags::INIT_JIT_CACHE)) { ensure_jit_cache_initialized(); } - + CUDF_FUNC_RANGE(); if (has_flag(flags, init_flags::LOAD_NVCOMP)) { io::detail::nvcomp::load_nvcomp_library(); } } +namespace { + /** * @brief Returns the path to the CUDF kernel cache directory. */ @@ -211,71 +210,50 @@ std::filesystem::path get_cudf_kernel_cache_dir() std::runtime_error); } -static std::optional _context{std::nullopt}; -static std::optional _context_init_flag{std::in_place}; -static std::optional _context_deinit_flag{std::in_place}; - -} // namespace cudf - -namespace CUDF_EXPORT cudf { - -void initialize(init_flags flags) +context make_context(init_flags flags) { - std::call_once(*_context_init_flag, [&]() { - auto const dump_codegen = detail::get_bool_env_or("LIBCUDF_JIT_DUMP_CODEGEN", false); - auto const use_jit = detail::get_bool_env_or("LIBCUDF_JIT_ENABLED", false); - auto const preload_jit_cache = detail::get_bool_env_or("LIBCUDF_KERNEL_CACHE_PRELOAD", false); - auto const disable_jit_cache = detail::get_bool_env_or("LIBCUDF_KERNEL_CACHE_DISABLED", false); - auto const clear_jit_cache = detail::get_bool_env_or("LIBCUDF_KERNEL_CACHE_CLEAR", false); - auto const disable_cuda_cache = - detail::get_bool_env_or("LIBCUDF_JIT_DISABLE_CUDA_CACHE", false); - auto const jit_verbose = detail::get_bool_env_or("LIBCUDF_JIT_VERBOSE", false); - auto const dump_jit_trace = detail::get_bool_env_or("LIBCUDF_JIT_DUMP_TRACE", false); - auto const dump_jit_time_profile = - detail::get_bool_env_or("LIBCUDF_JIT_DUMP_TIME_PROFILE", false); - - auto const kernel_cache_limit_process = - detail::getenv_or("LIBCUDF_KERNEL_CACHE_LIMIT_PER_PROCESS", 16'384U); - - flags = flags | (use_jit ? init_flags::INIT_JIT_CACHE : init_flags::NONE); - - auto const cache_dir = get_cudf_kernel_cache_dir(); - auto const jit_bundle_dir = cache_dir / "bundle"; - auto const rtcx_cache_dir = cache_dir / "rtcx_cache"; - auto const jit_pch_dir = cache_dir / "pch"; - auto const jit_tmp_dir = cache_dir / "tmp"; - - context_config cfg{.dump_codegen = dump_codegen, - .use_jit = use_jit, - .preload_jit_cache = preload_jit_cache, - .disable_jit_cache = disable_jit_cache, - .clear_jit_cache = clear_jit_cache, - .disable_cuda_cache = disable_cuda_cache, - .jit_verbose = jit_verbose, - .dump_jit_trace = dump_jit_trace, - .dump_jit_time_profile = dump_jit_time_profile, - .rtcx_cache_dir = rtcx_cache_dir, - .jit_bundle_dir = jit_bundle_dir, - .jit_pch_dir = jit_pch_dir, - .jit_tmp_dir = jit_tmp_dir, - .kernel_cache_limit_process = kernel_cache_limit_process}; - - _context.emplace(cfg, flags); - }); - - _context->initialize_components(flags); + auto const dump_codegen = detail::get_bool_env_or("LIBCUDF_JIT_DUMP_CODEGEN", false); + auto const use_jit = detail::get_bool_env_or("LIBCUDF_JIT_ENABLED", false); + auto const preload_jit_cache = detail::get_bool_env_or("LIBCUDF_KERNEL_CACHE_PRELOAD", false); + auto const disable_jit_cache = detail::get_bool_env_or("LIBCUDF_KERNEL_CACHE_DISABLED", false); + auto const clear_jit_cache = detail::get_bool_env_or("LIBCUDF_KERNEL_CACHE_CLEAR", false); + auto const disable_cuda_cache = detail::get_bool_env_or("LIBCUDF_JIT_DISABLE_CUDA_CACHE", false); + auto const jit_verbose = detail::get_bool_env_or("LIBCUDF_JIT_VERBOSE", false); + auto const dump_jit_trace = detail::get_bool_env_or("LIBCUDF_JIT_DUMP_TRACE", false); + auto const dump_jit_time_profile = + detail::get_bool_env_or("LIBCUDF_JIT_DUMP_TIME_PROFILE", false); + auto const preload_nvcomp = detail::get_bool_env_or("LIBCUDF_NVCOMP_PRELOAD", false); + + auto const kernel_cache_limit_process = + detail::getenv_or("LIBCUDF_KERNEL_CACHE_LIMIT_PER_PROCESS", 16'384U); + + auto const cache_dir = get_cudf_kernel_cache_dir(); + auto const jit_bundle_dir = cache_dir / "bundle"; + auto const rtcx_cache_dir = cache_dir / "rtcx_cache"; + auto const jit_pch_dir = cache_dir / "pch"; + auto const jit_tmp_dir = cache_dir / "tmp"; + + flags = flags | (preload_nvcomp ? init_flags::LOAD_NVCOMP : init_flags::NONE); + + context_config cfg{.dump_codegen = dump_codegen, + .use_jit = use_jit, + .preload_jit_cache = preload_jit_cache, + .disable_jit_cache = disable_jit_cache, + .clear_jit_cache = clear_jit_cache, + .disable_cuda_cache = disable_cuda_cache, + .jit_verbose = jit_verbose, + .dump_jit_trace = dump_jit_trace, + .dump_jit_time_profile = dump_jit_time_profile, + .rtcx_cache_dir = rtcx_cache_dir, + .jit_bundle_dir = jit_bundle_dir, + .jit_pch_dir = jit_pch_dir, + .jit_tmp_dir = jit_tmp_dir, + .kernel_cache_limit_process = kernel_cache_limit_process}; + + return context{cfg, flags}; } -void teardown() -{ - std::call_once(*_context_deinit_flag, [&]() { - // reset the context to destroy all global objects and release resources, allowing for clean - // re-initialization in the future if desired. - _context.reset(); - _context_init_flag.emplace(); - _context_deinit_flag.emplace(); - }); -} +} // namespace void enable_jit_cache(bool enabled) { @@ -290,10 +268,16 @@ void clear_jit_cache() cache.clear_disk_store(); } -context& get_context() +context& get_context(init_flags flags) { - cudf::initialize(); - return *_context; + static context instance = make_context(flags); + return instance; } -} // namespace CUDF_EXPORT cudf +namespace detail { + +void initialize(init_flags flags) { get_context(flags); } + +} // namespace detail + +} // namespace cudf diff --git a/cpp/src/runtime/context.hpp b/cpp/src/runtime/context.hpp index 98baeb586385..4b7323d5987d 100644 --- a/cpp/src/runtime/context.hpp +++ b/cpp/src/runtime/context.hpp @@ -62,9 +62,11 @@ class context { std::optional _nvjitlink_version; private: - void ensure_nvcomp_loaded(); + void preload_nvcomp(); - void ensure_jit_cache_initialized(); + void initialize_jit(); + + void initialize_components(init_flags flags); public: context(context_config cfg = {}, init_flags flags = init_flags::DEFAULT); @@ -91,13 +93,9 @@ class context { [[nodiscard]] std::optional nvrtc_version() const; [[nodiscard]] std::optional nvjitlink_version() const; - - /// @brief Initialize additional components based on the provided flags - /// @param flags The initialization flags to process - void initialize_components(init_flags flags); }; /// @brief Get the cuDF global context -context& get_context(); +context& get_context(init_flags flags = init_flags::DEFAULT); } // namespace cudf diff --git a/cpp/tests/utilities_tests/context_tests.cpp b/cpp/tests/utilities_tests/context_tests.cpp index 8c66e337dbf5..3213bf9ab205 100644 --- a/cpp/tests/utilities_tests/context_tests.cpp +++ b/cpp/tests/utilities_tests/context_tests.cpp @@ -14,33 +14,17 @@ #include -struct ContextTest : public cudf::test::BaseFixture { - ~ContextTest() override - { - try { - cudf::teardown(); - } catch (...) { - } - } -}; +struct ContextTest : public cudf::test::BaseFixture {}; TEST_F(ContextTest, MultipleInitializeCalls) { - cudf::initialize(cudf::init_flags::INIT_JIT_CACHE); - - EXPECT_NO_THROW(cudf::initialize(cudf::init_flags::LOAD_NVCOMP)); - EXPECT_NO_THROW(cudf::initialize(cudf::init_flags::ALL)); -} - -TEST_F(ContextTest, InitializeAfterTeardown) -{ - cudf::initialize(cudf::init_flags::ALL); - cudf::teardown(); + cudf::detail::initialize(cudf::init_flags::DEFAULT); - EXPECT_NO_THROW(cudf::initialize(cudf::init_flags::INIT_JIT_CACHE)); + EXPECT_NO_THROW(cudf::detail::initialize(cudf::init_flags::LOAD_NVCOMP)); + EXPECT_NO_THROW(cudf::detail::initialize(cudf::init_flags::ALL)); } -TEST_F(ContextTest, TeardownAfterJitCacheUse) +TEST_F(ContextTest, JitCacheUse) { auto compute_column = [] { auto c_0 = cudf::test::fixed_width_column_wrapper{3, 20, 1, 50}; @@ -54,23 +38,11 @@ TEST_F(ContextTest, TeardownAfterJitCacheUse) EXPECT_EQ(result->size(), cudf::size_type{4}); }; - cudf::initialize(cudf::init_flags::INIT_JIT_CACHE); + cudf::detail::initialize(cudf::init_flags::DEFAULT); ASSERT_NO_THROW(compute_column()); - EXPECT_NO_THROW(cudf::teardown()); - cudf::initialize(cudf::init_flags::INIT_JIT_CACHE); + cudf::detail::initialize(cudf::init_flags::DEFAULT); ASSERT_NO_THROW(compute_column()); - EXPECT_NO_THROW(cudf::teardown()); -} - -TEST_F(ContextTest, TeardownWithoutInitialize) { EXPECT_NO_THROW(cudf::teardown()); } - -TEST_F(ContextTest, MultipleTeardownCalls) -{ - cudf::initialize(cudf::init_flags::ALL); - cudf::teardown(); - - EXPECT_NO_THROW(cudf::teardown()); } template @@ -93,11 +65,11 @@ TEST_F(ContextTest, MultipleInitializeCallsMultiThreaded) auto init_task = [](size_t thread_id) { auto role = thread_id % 3; if (role == 0) { - EXPECT_NO_THROW(cudf::initialize(cudf::init_flags::INIT_JIT_CACHE)); + EXPECT_NO_THROW(cudf::detail::initialize(cudf::init_flags::DEFAULT)); } else if (role == 1) { - EXPECT_NO_THROW(cudf::initialize(cudf::init_flags::LOAD_NVCOMP)); + EXPECT_NO_THROW(cudf::detail::initialize(cudf::init_flags::LOAD_NVCOMP)); } else { - EXPECT_NO_THROW(cudf::initialize(cudf::init_flags::ALL)); + EXPECT_NO_THROW(cudf::detail::initialize(cudf::init_flags::ALL)); } }; EXPECT_NO_FATAL_FAILURE(run_multithreaded(init_task)); From 5048e2dacf8e50605aa003a2f3a2fe689e8b212b Mon Sep 17 00:00:00 2001 From: Basit Ayantunde Date: Fri, 21 Aug 2026 18:26:57 +0100 Subject: [PATCH 2/3] Improve documentation for cudf context initialization function --- cpp/include/cudf/context.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cpp/include/cudf/context.hpp b/cpp/include/cudf/context.hpp index 5ec8b975221b..b10c1c264002 100644 --- a/cpp/include/cudf/context.hpp +++ b/cpp/include/cudf/context.hpp @@ -66,9 +66,11 @@ constexpr bool has_flag(init_flags flags, init_flags flag) noexcept namespace detail { -/// @brief Ensure the cudf global context is initialized. Only the first call to this function will have an effect, subsequent calls are no-ops. -/// This function is thread-safe and can be called from multiple threads concurrently. -/// It is intended for library advanced users who need to explicitly control the initialization order of the cuDF context. Most users should not need to call this function directly, as the context is automatically initialized when needed. +/// @brief Ensure the cudf global context is initialized. Only the first call to this function will +/// have an effect, subsequent calls are no-ops. This function is thread-safe and can be called from +/// multiple threads concurrently. It is intended for library advanced users who need to explicitly +/// control the initialization order of the cuDF context. Most users should not need to call this +/// function directly, as the context is automatically initialized when needed. /// @param flags Optional flags controlling which components to initialize void initialize(init_flags flags = init_flags::DEFAULT); From f599482056d1b4db0e9ce6759974f00f5fe4ddf8 Mon Sep 17 00:00:00 2001 From: Basit Ayantunde Date: Sat, 22 Aug 2026 04:36:06 +0000 Subject: [PATCH 3/3] Refactor initialization flags and update context initialization logic --- cpp/include/cudf/context.hpp | 15 +++++++++------ cpp/src/runtime/context.cpp | 3 +-- cpp/src/runtime/context.hpp | 2 -- cpp/tests/utilities_tests/context_tests.cpp | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/cpp/include/cudf/context.hpp b/cpp/include/cudf/context.hpp index b10c1c264002..622d669eb58d 100644 --- a/cpp/include/cudf/context.hpp +++ b/cpp/include/cudf/context.hpp @@ -20,7 +20,7 @@ enum class init_flags : std::uint32_t { LOAD_NVCOMP = 1 << 0, /// @brief Default initialization steps DEFAULT = LOAD_NVCOMP, - /// @brief All initialization steps (default behavior) + /// @brief All initialization steps ALL = LOAD_NVCOMP }; @@ -67,11 +67,14 @@ constexpr bool has_flag(init_flags flags, init_flags flag) noexcept namespace detail { /// @brief Ensure the cudf global context is initialized. Only the first call to this function will -/// have an effect, subsequent calls are no-ops. This function is thread-safe and can be called from -/// multiple threads concurrently. It is intended for library advanced users who need to explicitly -/// control the initialization order of the cuDF context. Most users should not need to call this -/// function directly, as the context is automatically initialized when needed. -/// @param flags Optional flags controlling which components to initialize +/// have an effect, subsequent calls are no-ops regardless of the initialization flags. +/// This function is thread-safe and can be called from multiple threads concurrently. +/// +/// It is intended for advanced users who need to explicitly control the initialization order of the +/// cuDF context. Most users should not need to call this function directly, as the context is +/// automatically initialized when needed. +/// +/// @param flags Flags controlling which components to initialize void initialize(init_flags flags = init_flags::DEFAULT); } // namespace detail diff --git a/cpp/src/runtime/context.cpp b/cpp/src/runtime/context.cpp index 8af09f068da4..1554562734ba 100644 --- a/cpp/src/runtime/context.cpp +++ b/cpp/src/runtime/context.cpp @@ -52,7 +52,6 @@ int32_t get_current_device_compute_capability() context::context(context_config cfg, init_flags flags) : _config{std::move(cfg)}, - _jit_cache_init_flag{}, _device_properties{ get_driver_version(), get_runtime_version(), get_current_device_compute_capability()}, _nvrtc_version{0}, @@ -132,7 +131,7 @@ std::optional context::nvjitlink_version() const { return _nvjitlink_ve void context::initialize_components(init_flags flags) { CUDF_FUNC_RANGE(); - if (has_flag(flags, init_flags::LOAD_NVCOMP)) { io::detail::nvcomp::load_nvcomp_library(); } + if (has_flag(flags, init_flags::LOAD_NVCOMP)) { preload_nvcomp(); } } namespace { diff --git a/cpp/src/runtime/context.hpp b/cpp/src/runtime/context.hpp index 4b7323d5987d..65d48f87146a 100644 --- a/cpp/src/runtime/context.hpp +++ b/cpp/src/runtime/context.hpp @@ -9,7 +9,6 @@ #include #include -#include #include namespace rtcx { @@ -54,7 +53,6 @@ class context { private: context_config _config; - std::once_flag _jit_cache_init_flag; std::unique_ptr _rtcx_cache; std::unique_ptr _jit_bundle; device_properties _device_properties; diff --git a/cpp/tests/utilities_tests/context_tests.cpp b/cpp/tests/utilities_tests/context_tests.cpp index 3213bf9ab205..668b31396e92 100644 --- a/cpp/tests/utilities_tests/context_tests.cpp +++ b/cpp/tests/utilities_tests/context_tests.cpp @@ -65,7 +65,7 @@ TEST_F(ContextTest, MultipleInitializeCallsMultiThreaded) auto init_task = [](size_t thread_id) { auto role = thread_id % 3; if (role == 0) { - EXPECT_NO_THROW(cudf::detail::initialize(cudf::init_flags::DEFAULT)); + EXPECT_NO_THROW(cudf::detail::initialize(cudf::init_flags::NONE)); } else if (role == 1) { EXPECT_NO_THROW(cudf::detail::initialize(cudf::init_flags::LOAD_NVCOMP)); } else {