/************************************************************************* * Copyright (c) 2026 Advanced Micro Devices, Inc. All rights reserved. * * See LICENSE.txt for license information ************************************************************************/ // Shared CE test utilities – include in CeMPITests.cpp and CeInternalMPITests.cpp. #ifndef CE_TEST_HELPERS_HPP #define CE_TEST_HELPERS_HPP #ifdef MPI_TESTS_ENABLED #include "DeviceBufferHelpers.hpp" #include "MPIHelpers.hpp" #include // Returns true when compiled with CE batch API support (CE_BATCH_ASYNC_SUPPORTED). // Gated at build time via check_symbol_exists(hipMemcpyBatchAsync); no runtime query needed. inline constexpr bool isCeDriverSupported() { #ifdef CE_BATCH_ASYNC_SUPPORTED return true; #else return false; #endif } // Runtime driver-version gate mirroring ncclCeImplemented(): ROCm 7.12+ (>= 71200000) or the 7.0.2.x backport range [70051831, 70060000). inline bool isCeRuntimeDriverSupported() { int driverVer = 0; if(hipDriverGetVersion(&driverVer) != hipSuccess) return false; return (driverVer >= 71200000) || (driverVer >= 70051831 && driverVer < 70060000); } // Full CE dispatch gate // Returns true when all prerequisites for CE dispatch are satisfied: // 1. Binary compiled with CE batch API support (CE_BATCH_ASYNC_SUPPORTED). // 2. Running driver in the CE-supported range (matches ncclCeImplemented()). // 3. NCCL_CTA_POLICY=2 (CE dispatch mode). // 4. NCCL_LOCAL_REGISTER=0 (explicit buffer registration only). // 5. NCCL_CUMEM_ENABLE=1 (VMM-backed symmetric memory; default is 0). // Without this, comm->symmetricSupport is false and CE is never dispatched. // // Use this single check wherever a test needs to decide between asserting the // CE path or the SM fallback path. inline bool isCeDispatchConfigured() { // Required values constexpr int kCtaPolicyCE = 2; // NCCL_CTA_POLICY=2 → CE dispatch constexpr int kLocalRegisterCE = 0; // NCCL_LOCAL_REGISTER=0 → explicit registration constexpr int kCuMemEnable = 1; // NCCL_CUMEM_ENABLE=1 → symmetric VMM memory // NCCL/RCCL compiled-in defaults (returned when the env var is unset) constexpr int kCtaPolicyDefault = 0; // SM path constexpr int kLocalRegisterDefault = 1; // implicit registration enabled constexpr int kCuMemEnableDefault = 0; // VMM/symmetric memory disabled return isCeDriverSupported() && isCeRuntimeDriverSupported() && MPIHelpers::getEnvParam("NCCL_CTA_POLICY", kCtaPolicyDefault) == kCtaPolicyCE && MPIHelpers::getEnvParam("NCCL_LOCAL_REGISTER", kLocalRegisterDefault) == kLocalRegisterCE && MPIHelpers::getEnvParam("NCCL_CUMEM_ENABLE", kCuMemEnableDefault) == kCuMemEnable; } // Batch path prediction helpers // Mirrors the thresholds from ce_coll.cc (CE_COLL_INTRA_BATCH_SYNC_FREQ / // CE_COLL_INTRA_BATCH_SYNC_MSG_THRESHOLD). Kept here so the source file does // not need to expose internal constants via its header. static constexpr uint32_t kCeIntraBatchSyncFreq = 8; static constexpr uint64_t kCeIntraBatchSyncMsgThreshold = 512ULL * 1024 * 1024; // Returns true when the CE batch path will use intraBatchSync, given the // actual numOps and chunkBytes for a collective. Mirrors the condition in // ncclCeLaunchBatchOps() so tests can assert the correct path sub-variant. inline bool ceExpectIntraBatchSync(size_t numOps, size_t chunkBytes) { return numOps > kCeIntraBatchSyncFreq && chunkBytes * numOps >= kCeIntraBatchSyncMsgThreshold; } // Shared buffer helpers // Fill buf[0..nElem) with float(rank + 1) on the GPU. // Returns hipSuccess on success; caller should ASSERT_EQ on the result. inline hipError_t ceFillRankScalarFloat(void* buf, size_t nElem, int rank) { return RCCLTestHelpers::initializeBufferWithPattern( buf, nElem, [rank](size_t) { return static_cast(rank + 1); }); } // Verify AllGather / AlltoAll output: element at index i must equal // float(i / elemsPerRank + 1), i.e. each rank's block contains float(rank+1). // Returns true when all elements match. inline bool ceVerifyBlockPatternFloat(const void* buf, size_t totalElem, size_t elemsPerRank) { return RCCLTestHelpers::verifyBufferData( buf, totalElem, [elemsPerRank](size_t i) { return static_cast(i / elemsPerRank + 1); }); } #endif // MPI_TESTS_ENABLED #endif // CE_TEST_HELPERS_HPP