Files
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

108 lines
4.6 KiB
C++

/*************************************************************************
* Copyright (c) 2026 Advanced Micro Devices, Inc. All rights reserved.
*
* See LICENSE.txt for license information
************************************************************************/
#include "TestBed.hpp"
namespace RcclUnitTesting
{
// Stress coverage for the parallelized TestBed::DestroyComms teardown
// (ROCM-25953): DestroyComms now broadcasts the destroy command to every child
// process first and collects the acknowledgements in a second pass, so the
// children tear their communicators down concurrently instead of one at a time.
// These tests drive that path repeatedly, in multi-process mode (one child per
// GPU) where the two-pass ordering actually matters, and in both blocking and
// non-blocking modes (the child-side DestroyComms branches on useBlocking).
namespace
{
// Returns true if ncclFloat32 is available under the current UT_DATATYPES.
// Checked once in each test body so the test can GTEST_SKIP() explicitly
// rather than silently passing as a no-op when the datatype is excluded.
bool float32Supported(TestBed& testBed)
{
std::vector<ncclDataType_t> dataTypes;
testBed.GetSupportedDataTypes(dataTypes, {ncclFloat32});
return !dataTypes.empty();
}
// Run `iterations` init / collective / destroy cycles over `totalRanks`
// ranks, one child process per rank. Each cycle ends in DestroyComms, the
// path under test. A leaked pipe fd or child handle, or any mismatch between
// the broadcast pass and the ack-collection pass, shows up as a hang or a
// failure once enough cycles accumulate.
void RunTeardownCycles(TestBed& testBed,
int const totalRanks,
bool const useBlocking,
int const iterations,
bool& isCorrect)
{
size_t const numElements = 32 * 1024;
bool const inPlace = false;
bool const useManagedMem = false;
int const numProcesses = totalRanks; // one child process per rank
const std::vector<int>& gpuPriorityOrder = testBed.ev.GetGpuPriorityOrder();
for (int iter = 0; iter < iterations && isCorrect; ++iter)
{
testBed.InitComms(TestBed::GetDeviceIdsList(numProcesses, totalRanks,
gpuPriorityOrder),
1, 1, 1, useBlocking);
OptionalColArgs options;
options.redOp = ncclSum;
testBed.SetCollectiveArgs(ncclCollAllReduce, ncclFloat32,
numElements, numElements, options);
testBed.AllocateMem(inPlace, useManagedMem);
testBed.PrepareData();
testBed.ExecuteCollectives();
testBed.ValidateResults(isCorrect);
testBed.DeallocateMem();
testBed.DestroyComms();
}
}
}
// Repeated multi-process teardown in both blocking and non-blocking modes.
TEST(Teardown, RepeatedDestroyComms)
{
TestBed testBed;
if (testBed.ev.maxGpus < 2)
GTEST_SKIP() << "Teardown stress requires at least 2 GPUs (detected "
<< testBed.ev.maxGpus << ")";
if (!(testBed.ev.processMask & (1 << 1)))
GTEST_SKIP() << "Teardown stress requires multi-process mode (UT_PROCESS_MASK)";
if (!float32Supported(testBed))
GTEST_SKIP() << "Teardown stress requires ncclFloat32 (excluded by UT_DATATYPES)";
bool isCorrect = true;
for (bool useBlocking : {true, false})
RunTeardownCycles(testBed, testBed.ev.maxGpus, useBlocking,
/*iterations*/ 3, isCorrect);
EXPECT_TRUE(isCorrect);
testBed.Finalize();
}
// Teardown across a varying number of child processes within one test, so
// DestroyComms is exercised with different numActiveChildren values back to
// back. Catches assumptions that only hold for a fixed child count.
TEST(Teardown, DestroyCommsVaryingChildCount)
{
TestBed testBed;
if (testBed.ev.maxGpus < 2)
GTEST_SKIP() << "Teardown stress requires at least 2 GPUs (detected "
<< testBed.ev.maxGpus << ")";
if (!(testBed.ev.processMask & (1 << 1)))
GTEST_SKIP() << "Teardown stress requires multi-process mode (UT_PROCESS_MASK)";
if (!float32Supported(testBed))
GTEST_SKIP() << "Teardown stress requires ncclFloat32 (excluded by UT_DATATYPES)";
bool isCorrect = true;
for (int ranks = testBed.ev.maxGpus; ranks >= 2 && isCorrect; ranks /= 2)
RunTeardownCycles(testBed, ranks, /*useBlocking*/ true,
/*iterations*/ 1, isCorrect);
EXPECT_TRUE(isCorrect);
testBed.Finalize();
}
}