Files
TheRock/rocm-systems/projects/rccl/examples/03_collectives/01_allreduce
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
..

NCCL AllReduce Collective Operation Example

This example demonstrates the fundamental AllReduce collective operation using NCCL's single-process, multi-GPU approach in which a single process manages all GPUs to perform a sum reduction.

Overview

AllReduce combines data from all participants using a reduction operation (sum, max, min, etc.) and distributes the result to all participants. This example shows how each GPU contributes its rank value and all GPUs receive the combined sum using ncclCommInitAll for simplified setup.

What This Example Does

  1. Detects available GPUs and initializes NCCL communicators for all devices using ncclCommInitAll
  2. Initializes data with each GPU contributing its rank value (GPU 0→0, GPU 1→1, etc.)
  3. Performs AllReduce sum operation where all GPU values are summed and distributed to all participants
  4. Verifies correctness by checking that all GPUs received the expected sum: 0+1+2+...+(n-1)

Building and Running

Build the Example

cd examples/03_collectives/01_allreduce
make [ROCM_PATH=<path-to-rocm>] [RCCL_HOME=<path-to-rccl>]

Run with All Available GPUs

./allreduce

Run with Specific GPUs

HIP_VISIBLE_DEVICES=0,1,2,3 ./allreduce

Code Walk-through

Data Initialization

Each GPU sets a send buffer allocated on the GPU to its rank value:

float** sendbuff;
float rank_value = (float)i;
size_t size; // size is the number of float to be sent

// Allocate device memory for send buffers
CUDACHECK(hipMalloc((void **)&sendbuff[i], size * sizeof(float)));

// Each GPU contributes its rank (GPU i contributes value i)
// Zero the entire buffer, then set first element to rank
CUDACHECK(hipMemset(sendbuff[i], 0, size * sizeof(float)));
CUDACHECK(hipMemcpy(sendbuff[i], &rank_value, sizeof(float), hipMemcpyHostToDevice));

AllReduce Operation

All GPUs participate in the sum reduction. The operations are evaluated in parallel within a NCCL group to avoid any deadlocks.

float** recvbuff;
ncclComm_t *comms;  // comms are set during ncclCommInitAll
hipStream_t *streams; // streams are set in hipStreamCreate

// Allocate device memory for receive buffers
CUDACHECK(hipMalloc((void **)&recvbuff[i], size * sizeof(float)));

NCCLCHECK(ncclGroupStart());
for (int i = 0; i < num_gpus; i++) {
    NCCLCHECK(ncclAllReduce(sendbuff[i], recvbuff[i], size, ncclFloat,
                            ncclSum, comms[i], streams[i]));
}
NCCLCHECK(ncclGroupEnd());

Expected Output

Using 4 devices for collective communication
Memory allocated for 4 communicators and streams
NCCL communicators initialized for all devices
  Device 0 initialized with data value 0
  Device 1 initialized with data value 1
  Device 2 initialized with data value 2
  Device 3 initialized with data value 3
Starting collective sum operation across all devices
Collective operation completed
Verifying results (expected sum: 6)
  Device 0 correctly received sum: 6
  Device 1 correctly received sum: 6
  Device 2 correctly received sum: 6
  Device 3 correctly received sum: 6
Example completed successfully!

When to Use

  • Deep learning: Gradient averaging in data-parallel training
  • Scientific computing: Global reductions in parallel algorithms
  • Statistics: Computing global sums, averages, or other reductions
  • Distributed algorithms: Any scenario requiring collective reduction operations

Key Insights

  • ncclCommInitAll simplifies single-node multi-GPU setup
  • No MPI or pthreads needed for single-node patterns
  • Allocate device buffer via hipMalloc and initialize via hipMemset.
  • Best practices to wrap all collective calls in ncclGroupStart/End
  • All communication happens in parallel

Common Issues and Solutions

Issue: Verification failures

Solution: Ensure each GPU initializes its buffer correctly with its rank value.

Issue: Out of memory errors

Solution: Reduce the buffer size in the code or use fewer GPUs.

Error Handling

This example uses comprehensive error checking with NCCLCHECK and CUDACHECK macros that immediately exit on any failure. In production code, consider more graceful error handling and recovery mechanisms.

Next Steps

After understanding AllReduce, explore:

  • Point-to-point communication: Examples in 02_point_to_point/
  • Other collectives: Implement Broadcast, Reduce, AllGather operations using this example
  • Multi-node approach: Use the MPI implementation from 01_communicators to send data across nodes.