Skip to content
Merged
3 changes: 1 addition & 2 deletions cpp/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
# SPDX-License-Identifier: Apache-2.0
# cmake-format: on

set(UTIL_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/utilities/seed_generator.cu
${CMAKE_CURRENT_SOURCE_DIR}/utilities/logger.cpp
set(UTIL_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/utilities/logger.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utilities/version_info.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utilities/timestamp_utils.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utilities/work_unit_scheduler.cpp)
Expand Down
10 changes: 0 additions & 10 deletions cpp/src/utilities/seed_generator.cu

This file was deleted.

28 changes: 22 additions & 6 deletions cpp/src/utilities/seed_generator.cuh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* clang-format off */
/*
* SPDX-FileCopyrightText: Copyright (c) 2023-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
/* clang-format on */
Expand All @@ -9,20 +9,36 @@
#include <raft/random/rng_device.cuh>
#include <utilities/cuda_helpers.cuh>

#include <atomic>
#include <cstdint>
#include <random>

namespace cuopt {

// TODO: should be thread local?
/**
* @brief Source of deterministic seeds for a single cuOpt solver library.
*
* The counter is defined inline, so each library that links this header keeps its own.
* That matches how the seed is actually supplied: routing derives it from the problem
* geometry while mathematical optimization takes it from the user's solver settings.
* Those are independent inputs, and a single shared counter meant whichever solver ran
* last silently overwrote the other's seed.
*
* @note Thread-safe. get_seed() hands out distinct values to concurrent callers, but the
* order in which they are handed out is not deterministic; reproducibility across
* runs therefore still requires a deterministic call order.
*/
class seed_generator {
static int64_t seed_;
static inline std::atomic<int64_t> seed_{0};

public:
template <typename seed_t>
static void set_seed(seed_t seed)
{
#ifdef BENCHMARK
seed_ = std::random_device{}();
seed_.store(std::random_device{}(), std::memory_order_relaxed);
#else
seed_ = static_cast<int64_t>(seed);
seed_.store(static_cast<int64_t>(seed), std::memory_order_relaxed);
#endif
}
template <typename arg0, typename arg1, typename... args>
Expand All @@ -31,7 +47,7 @@ class seed_generator {
set_seed(seed1 + ((seed0 + seed1) * (seed0 + seed1 + 1) / 2), seeds...);
}

static int64_t get_seed() { return seed_++; }
static int64_t get_seed() { return seed_.fetch_add(1, std::memory_order_relaxed); }

public:
seed_generator(seed_generator const&) = delete;
Expand Down
Loading