#288 - Add UCX GPU egress example - #289
Draft
dleshchev wants to merge 1 commit into
Draft
Conversation
Signed-off-by: Denis Leshchev <dleshchev@nvidia.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds an opt-in two-host example that combines DAQIRI raw-Ethernet ingress, batched CUDA processing, and reliable UCP messaging over RoCEv2:
DAQIRI and UCX run in the same Host B process while retaining independent progress threads and separate physical NIC ports. The example is application-local: it does not add another DAQIRI engine, change DAQIRI's single-engine model, or add a general-purpose reorder API.
What is implemented
Staged example applications
The example provides three executables:
daqiri_ucx_raw_sourcegenerates deterministic packetized input over raw Ethernet.daqiri_ucx_raw_pipelinesupportsassemble,process, andegressstages so raw RX, CUDA processing, and the composed pipeline can be measured independently.daqiri_ucx_gpu_transport_benchexercises the same producer and receiver components with generated payloads, allowing UCX/RDMA behavior to be validated without DAQIRI ingress.The demonstration workload uses 256×256
uint16images. Sixteen packet fragments form an image and sixteen images form one 2 MiB CUDA processing batch. A CUDA ordering/placement kernel assembles the input, followed by an in-place scale-and-offset transform with defined saturation and rounding behavior.Application-local raw assembly
Every source packet carries a small versioned DQRI header containing its source epoch, batch ID, packet sequence, fragment index, payload length, and header checksum. The assembler uses these fields and a fragment bitmap to accept in-batch reordering while rejecting missing, duplicate, malformed, timed-out, or cross-batch input.
This intentionally avoids depending on DAQIRI's existing arrival-count reorder window for application image boundaries. It remains an example protocol rather than a new public DAQIRI API.
Thread and buffer ownership
Host B uses distinct owners for:
DAQIRI bursts remain RX-owned until CUDA has finished reading their packet data. Processing slots use generation-checked, move-only leases across the RX → CUDA → UCX lifecycle. The UCX producer records a reusable CUDA event on the processing stream and submits a payload only after that event completes. A producer slot is returned to RX only after every UCP send referencing it completes and RX observes its retirement.
On the receiver, successful UCP receive completion makes a move-only
ReceivedImageavailable to application code.release_after(cudaStream_t)returns the associated credit only after downstream GPU work on that stream has completed.UCP protocol and overload behavior
Data uses two-sided UCP Active Message rendezvous. A CPU-visible serialized header describes each payload, and the receiver selects a registered GPU-accessible destination before calling
ucp_am_recv_data_nbx().Small Active Messages implement
HELLO,ACCEPT,REJECT, cumulativeCREDIT,EOS, andEOS_ACK. Receiver slots provide bounded message credits. When no credit is available, the producer drops new output before UCP submission; admitted messages are not deliberately dropped. Monotonic sequence numbers expose those overload drops as receiver gaps.The implementation keeps these completion boundaries distinct:
Build and documentation
The new
ucxcontainer target builds UCX 1.20 with UCP, verbs, mlx5, RDMA-CM, and CUDA-memory support.DAQIRI_BUILD_UCX_GPU_EGRESSenables the example beneath the existingDAQIRI_BUILD_APPLICATIONSgate.The application includes portable placeholder configurations, an application README, and a website tutorial modeled after the ResNet50 inference example.
Two-Spark validation
The complete pipeline was validated using two DGX Spark systems and two separate 100-Gbit/s links:
det1for raw-Ethernet source and DAQIRI ingress.det4for UCP/RoCEv2 egress and receive.det1anddet4have different PCIe prefixes on this setup. BothUCX_NET_DEVICESandUCX_IB_GID_INDEXwere explicitly pinned. UCX protocol logging selectedrc_mlx5rendezvous on the intended Link 2 ports.UCX-only result
Complete pipeline result
These Spark results use mapped pinned host memory.
cuda_deviceremains supported for validation on another platform, but this PR does not claim GPUDirect RDMA for CUDA device memory merely because UCX accepts the pointer.Validation performed
git diff --checkand project formatting checks.mlnx_perf.Scope and limitations
Closes #288