Use the RCCL device API and GIN#
The experimental RCCL device API lets GPU kernels communicate through a
device communicator (ncclDevComm). GPU-initiated networking (GIN) extends
that API with one-sided puts, signals, counters, and barriers across nodes.
RCCL 2.30.4 incorporates Device API and GIN enhancements from upstream
NCCL 2.30.3. This page describes those APIs and the limits of the AMD
host-proxy backend.
Requirements#
GIN requires a supported network backend, symmetric memory, and collective
communicator and window setup. The validated AMD path is GIN_IB_PROXY:
export NCCL_GIN_TYPE=2
export NCCL_CUMEM_ENABLE=1
export NCCL_DMABUF_ENABLE=1
export NCCL_IB_MERGE_NICS=0
The ROCm runtime and NIC driver must support exporting and registering VMM
allocations. NCCL_DMABUF_ENABLE=1 is the validated registration path;
peer-memory registration can also be available on supported systems. Full GIN
connections require cross-rail reachability, so do not force
NCCL_CROSS_NIC=0 for world-team operations. Leave ginQueueDepth at its
default value of zero; the AMD host-proxy backend does not support a custom QP
depth.
The following snippets abbreviate error handling with NCCLCHECK. Replace it
with the application’s normal ncclResult_t error handling.
Before using GIN, query communicator properties and confirm that the selected backend and Device API are available:
ncclCommProperties properties = NCCL_COMM_PROPERTIES_INITIALIZER;
NCCLCHECK(ncclCommQueryProperties(comm, &properties));
if (!properties.deviceApiSupport ||
properties.ginType != NCCL_GIN_TYPE_PROXY) {
// Select a non-GIN path or report that this configuration is unsupported.
}
Allocate and register every communication buffer collectively:
void* buffer = nullptr;
ncclWindow_t window = nullptr;
NCCLCHECK(ncclMemAlloc(&buffer, bytes));
NCCLCHECK(ncclCommWindowRegister(
comm, buffer, bytes, &window, NCCL_WIN_COLL_SYMMETRIC));
Create a device communicator#
Always initialize requirements with
NCCL_DEV_COMM_REQUIREMENTS_INITIALIZER. The initializer records the header
version used to compile the application.
ncclDevCommRequirements reqs = NCCL_DEV_COMM_REQUIREMENTS_INITIALIZER;
reqs.ginConnectionType = NCCL_GIN_CONNECTION_FULL;
reqs.ginContextCount = 4; // Hint; inspect devComm.ginContextCount.
reqs.ginSignalCount = 1;
reqs.ginCounterCount = 1;
reqs.barrierCount = 1; // Generic ncclBarrierSession.
reqs.worldGinBarrierCount = 1;
ncclDevComm devComm{};
NCCLCHECK(ncclDevCommCreate(comm, &reqs, &devComm));
GIN contexts and their signal, counter, and queue resources are allocated per
device communicator. Two device communicators backed by the same host
communicator therefore don’t alias those resources. ginContextCount is a
request; use the value returned in devComm.ginContextCount when assigning
work to contexts.
ginTrafficClass overrides the host communicator traffic class for this
device communicator. NCCL_IB_SL independently overrides the InfiniBand
service level, and NCCL_IB_TC independently overrides the RoCE traffic
class. Set reqs.ginTrafficClass only when the fabric administrator provides
an appropriate value.
Device code creates an ncclGin object for one returned context:
ncclGin gin{devComm, contextIndex, NCCL_GIN_RESOURCE_SHARING_GPU};
For example, a CTA can issue a put and wait for local queue completion:
__global__ void putKernel(
ncclDevComm devComm, ncclWindow_t source, ncclWindow_t destination,
size_t bytes, int peer) {
ncclGin gin{devComm, /*contextIndex=*/0};
if (threadIdx.x == 0) {
gin.put(ncclTeamWorld(devComm), peer,
destination, /*destinationOffset=*/0,
source, /*sourceOffset=*/0, bytes,
ncclGin_SignalInc{/*signal=*/0});
}
gin.flush(ncclCoopCta());
}
flush makes the local source buffer reusable. It does not by itself prove
remote visibility; the peer must wait for the associated signal before using
the destination bytes.
NCCL_GIN_RESOURCE_SHARING_GPU permits sharing across the GPU;
NCCL_GIN_RESOURCE_SHARING_CTA limits sharing to a CTA. These modes select
resource-sharing behavior on direct device backends. The AMD GIN host-proxy
backend uses the same proxy queue behavior for both modes.
Use world-team barriers and timeouts#
Reserve worldGinBarrierCount slots to construct a world-team GIN barrier
without manually allocating a barrier handle:
ncclGinBarrierSession<ncclCoopCta> barrier{
ncclCoopCta(), gin, ncclTeamTagWorld{}, barrierIndex};
ncclResult_t result = barrier.sync(
ncclCoopCta(), cuda::memory_order_acq_rel,
ncclGinFenceLevel::Relaxed, timeoutCycles);
The timeout overload returns ncclTimeout if all team members don’t arrive
within timeoutCycles. Barrier resources for ncclGinBarrierSession,
ncclLsaBarrierSession, and ncclBarrierSession are separate. Reserve
barrierCount for generic ncclBarrierSession objects; use
lsaBarrierCount, railGinBarrierCount, or worldGinBarrierCount for
the corresponding specialized session. barrierIndex must be smaller than
the selected count. Concurrent CTAs must use distinct indices, typically
blockIdx.x.
Destroy resources#
Destroy the device communicator before deregistering its application windows, then free the backing allocations. These calls are collective where their corresponding create or registration operation is collective.
NCCLCHECK(ncclDevCommDestroy(comm, &devComm));
NCCLCHECK(ncclCommWindowDeregister(comm, window));
NCCLCHECK(ncclMemFree(buffer));
Version and backend notes#
ncclDevComm is versioned. The upstream NCCL 2.30.3 and 2.30.4 release notes
require applications using GIN APIs to be rebuilt with the matching release.
RCCL accepts compatible layouts within the 2.30 family, but applications using
pre-2.30 GIN device code must be rebuilt with compatible RCCL headers. The
runtime rejects pre-2.30 requirements that request indexed GIN resources.
The 128-byte, versioned GIN proxy descriptor and per-context proxy progress are
internal implementation details and require no application configuration.
The max_rd_atomic and max_dest_rd_atomic changes and the
doca-gpunetio update in the NCCL 2.30 release apply to NVIDIA’s GDAKI
backend, not the AMD GIN host-proxy backend.
The source includes experimental proxy get and nonblocking-flush paths, but
they are not yet validated for production use on the AMD host-proxy backend.
GIN access to elastic and multi-segment windows is also unavailable on that
backend until a complete multi-segment VMM range can be exported for DMA-BUF
registration. Use the validated put/signal path with single-segment symmetric
windows.