Files
TheRock/rocm-systems/projects/rccl/test/common/HostApiHelpers.hpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

215 lines
6.8 KiB
C++

/*************************************************************************
* Copyright (c) 2026 Advanced Micro Devices, Inc. All rights reserved.
*
* See LICENSE.txt for license information
************************************************************************/
/**
* @file HostApiHelpers.hpp
* @brief Helper utilities for testing RCCL's one-sided RMA (Host API)
*
* Provides:
* - allocFineGrainBuffer / freeFineGrainBuffer via ncclMemAlloc / ncclMemFree
* - NcclWindowGuard: RAII wrapper for ncclCommWindowRegister / ncclCommWindowDeregister
* - fillPatternBytes / verifyPatternBytes for byte-level test patterns on CPU-accessible
* (fine-grain) memory
*
*/
#ifndef HOST_API_HELPERS_HPP
#define HOST_API_HELPERS_HPP
#ifdef MPI_TESTS_ENABLED
#include "rccl/rccl.h"
#include <hip/hip_runtime.h>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <vector>
namespace RCCLHostApiHelpers
{
// ============================================================================
// Fine-grain buffer allocation
// ============================================================================
/**
* @brief Allocate fine-grain (CPU-accessible) memory via ncclMemAlloc.
*
* On ROCm the returned pointer is host-accessible without hipMemcpy.
*
* @param ptr Out: receives allocated pointer.
* @param size Requested size in bytes.
* @return ncclResult_t from ncclMemAlloc.
*/
inline ncclResult_t allocFineGrainBuffer(void** ptr, size_t size)
{
return ncclMemAlloc(ptr, size);
}
/**
* @brief Free fine-grain memory previously allocated with allocFineGrainBuffer.
*
* @param ptr Pointer to free (no-op if nullptr).
* @return ncclResult_t from ncclMemFree, or ncclSuccess if ptr was nullptr.
*/
inline ncclResult_t freeFineGrainBuffer(void* ptr)
{
if(!ptr)
return ncclSuccess;
return ncclMemFree(ptr);
}
// ============================================================================
// RAII guard for ncclWindow_t
// ============================================================================
/**
* @struct NcclWindowGuard
* @brief RAII wrapper for ncclCommWindowRegister / ncclCommWindowDeregister.
*
* Constructor calls ncclCommWindowRegister. Destructor calls
* ncclCommWindowDeregister only if win_ is non-null.
*
* Usage:
* @code
* void* buf = nullptr;
* allocFineGrainBuffer(&buf, kSize);
* ncclWindow_t win = nullptr;
* NcclWindowGuard wg(comm, buf, kSize, &win, NCCL_WIN_DEFAULT);
* if (win == nullptr) { GTEST_SKIP() << "Windows not supported"; }
* // ... use win ...
* // Destructor calls ncclCommWindowDeregister automatically.
* @endcode
*/
struct NcclWindowGuard
{
ncclComm_t comm_ = nullptr;
ncclWindow_t win_ = nullptr;
ncclResult_t initResult_ = ncclSuccess;
NcclWindowGuard() = default;
/**
* @brief Register a memory window.
*
* @param comm RCCL communicator (collective across all ranks).
* @param buff Buffer to register (fine-grain, CPU-accessible).
* @param size Size of the buffer in bytes.
* @param winOut Out: receives the window handle.
* @param winFlags Window flags (use NCCL_WIN_DEFAULT = 0x00 for proxy GIN path).
*/
NcclWindowGuard(ncclComm_t comm,
void* buff,
size_t size,
ncclWindow_t* winOut,
int winFlags)
: comm_(comm)
{
initResult_ = ncclCommWindowRegister(comm_, buff, size, &win_, winFlags);
if(winOut)
*winOut = win_;
}
~NcclWindowGuard()
{
if(win_ && comm_)
{
ncclResult_t res = ncclCommWindowDeregister(comm_, win_);
if(res != ncclSuccess)
{
fprintf(stderr,
"WARNING: ncclCommWindowDeregister failed in destructor: %s\n",
ncclGetErrorString(res));
}
win_ = nullptr;
}
}
// Non-copyable, non-movable (owns the handle)
NcclWindowGuard(const NcclWindowGuard&) = delete;
NcclWindowGuard& operator=(const NcclWindowGuard&) = delete;
NcclWindowGuard(NcclWindowGuard&&) = delete;
NcclWindowGuard& operator=(NcclWindowGuard&&) = delete;
ncclResult_t initResult() const { return initResult_; }
ncclWindow_t win() const { return win_; }
bool valid() const { return win_ != nullptr; }
};
// ============================================================================
// Pattern fill / verify (hipMemcpy staging — works on device and fine-grain)
// ============================================================================
/** Fill buf with pattern (seed + i) % 256 via hipMemcpy staging. */
inline void FillBuf(void* buf, size_t size, int seed)
{
std::vector<uint8_t> tmp(size);
for(size_t i = 0; i < size; ++i)
tmp[i] = static_cast<uint8_t>((seed + i) % 256);
ASSERT_EQ(hipMemcpy(buf, tmp.data(), size, hipMemcpyHostToDevice), hipSuccess);
ASSERT_EQ(hipDeviceSynchronize(), hipSuccess);
}
/** Return true iff buf matches (seed + i) % 256 for all i. */
inline bool VerifyBuf(const void* buf, size_t size, int seed)
{
std::vector<uint8_t> staging(size);
if(hipMemcpy(staging.data(), buf, size, hipMemcpyDeviceToHost) != hipSuccess)
return false;
if (hipDeviceSynchronize() != hipSuccess)
return false;
for(size_t i = 0; i < size; ++i)
{
if(staging[i] != static_cast<uint8_t>((seed + i) % 256))
{
fprintf(stderr,
"VerifyBuf: mismatch at byte %zu: expected %u got %u (seed=%d)\n",
i,
static_cast<unsigned>((seed + i) % 256),
static_cast<unsigned>(staging[i]),
seed);
return false;
}
}
return true;
}
/** Fill buf with a constant sentinel byte via hipMemset. */
inline void FillSentinel(void* buf, size_t size, uint8_t value)
{
ASSERT_EQ(hipMemset(buf, value, size), hipSuccess);
ASSERT_EQ(hipDeviceSynchronize(), hipSuccess);
}
/** Return true iff every byte in buf equals value. */
inline bool AllSentinel(const void* buf, size_t size, uint8_t value)
{
std::vector<uint8_t> staging(size);
if(hipMemcpy(staging.data(), buf, size, hipMemcpyDeviceToHost) != hipSuccess)
return false;
if (hipDeviceSynchronize() != hipSuccess)
return false;
for(size_t i = 0; i < size; ++i)
{
if(staging[i] != value)
{
fprintf(stderr,
"AllSentinel: mismatch at byte %zu: expected 0x%02x got 0x%02x\n",
i,
static_cast<unsigned>(value),
static_cast<unsigned>(staging[i]));
return false;
}
}
return true;
}
} // namespace RCCLHostApiHelpers
#endif // MPI_TESTS_ENABLED
#endif // HOST_API_HELPERS_HPP