Skip to content

feat(cco): BNXT GDA per-packet PSN + per-peer doorbell grouping#421

Merged
jhchouuu merged 6 commits into
dev/ccofrom
jiahzhou/cco-gda-doorbell-bnxt-psn
Jun 24, 2026
Merged

feat(cco): BNXT GDA per-packet PSN + per-peer doorbell grouping#421
jhchouuu merged 6 commits into
dev/ccofrom
jiahzhou/cco-gda-doorbell-bnxt-psn

Conversation

@jhchouuu

Copy link
Copy Markdown
Collaborator

Summary

Targets cco's GDA (cross-node IBGDA) device path. Fixes BNXT correctness, regroups doorbells per peer (unblocking thread/warp-scope bandwidth), and adds benchmark instrumentation. All changes are BNXT-only on the device side; MLX5/IONIC behavior is preserved.

Verified on BNXT (rocm/mori:ci): all cco GDA tests pass single-node (fork) and cross-node (2-node a07u19↔a07u25, 16 ranks); p2p bandwidth saturates ~49 GB/s (≈98% of 400G line rate) across block/warp/thread scopes.

Commits

fix(cco): BNXT GDA per-packet PSN + reserve-gate drain

Ports the BNXT GDA correctness fixes onto #411's warp-aggregate architecture (all BNXT-only):

  • Per-packet PSN: BNXT PSN must advance by packet count (ceil(bytes/mtu)), not WQE-slot index. Reserved via wq->msnPack — per lane in reserveWqeSlots, and per warp via warpAggregateBnxtPsn (leader advances once, lanes take a prefix-ordered base). Applied to put / putValue / get / signal.
  • Reserve-gate drain: BNXT drains to the doorbelled snapshot (dbTouchIdx), not the un-doorbelled reservation, avoiding self-deadlock when WQEs are posted without an immediate doorbell. MLX5/IONIC keep their original drain target.
  • Error CQE: quietUntil traps on a non-OK BNXT completion instead of treating the error as progress.

perf(cco): group GDA doorbells per peer; unblock thread/warp-scope bw

  • put/get/putValue group active lanes by peer via a __ballot turn loop (only in the WarpDefault + CoopThread path); each peer reserves contiguously and the group leader rings one doorbell (new LeaderOnly template path). WarpAggregate / CoopWarp / CoopBlock are a single group and skip the loop.
  • Unified the BNXT/PSD anti-coalescing lane-walk into ringDoorbellWalk<PrvdType>, used by both ringDoorbellOrdered and flushAsyncImpl — fixing a missing walk on BNXT flush (a multi-peer flush could drop coalesced doorbells and hang).
  • Dropped __syncwarp from the lane-walk: AMD wavefronts are lock-step, so per-lane predication already orders the stores; __syncwarp was also a deadlock on divergent entry.
  • benchmark p2p bw drops ccoGdaOptFlagsAggregateRequests: per-op doorbell is now safe in thread/warp scope and waitSqSpace drains the CQ as the SQ fills, so the deferred-doorbell SQ overflow that hung those scopes is gone.

feat(cco-bench): perf-table instrumentation

  • msg + units columns: show how the total size is split (one WQE/message per cooperative unit) and the per-WQE size (size/units).
  • -s thread_agg: thread scope + ccoGdaWarpAggregate, to benchmark the aggregate path. On BNXT p2p it matches plain thread within noise (the per-peer grouping already aggregates same-peer warp lanes).
  • Mpps column: WQE/packet issue rate (GB/s * 1e3 * units / size). Exposes the issue-rate ceiling — ~115 Mpps flat for small messages (rate-bound) vs line-rate / low Mpps for large messages (bandwidth-bound).

jhchouuu and others added 6 commits June 23, 2026 13:27
…ate path

Port the BNXT GDA correctness fixes onto the warp-aggregate architecture
(#411). All three are BNXT-only; MLX5/IONIC behavior is unchanged.

- Per-packet PSN: BNXT PSN must advance by packet count (ceil(bytes/mtu)),
  not WQE-slot index. Reserve PSNs via wq->msnPack — per lane in
  reserveWqeSlots, and per warp via warpAggregateBnxtPsn (leader advances
  once, lanes take a prefix-ordered base). Applied to put/putValue/get/
  signal across both the per-lane and warp-aggregate paths.
- Reserve-gate drain: BNXT drains to the doorbelled snapshot (dbTouchIdx),
  not the un-doorbelled reservation, to avoid self-deadlock when WQEs are
  posted without an immediate doorbell. MLX5/IONIC keep draining to their
  own reservation.
- Error CQE: quietUntil checks the BNXT CQE opcode and traps on a non-OK
  completion instead of treating the error as progress.

Each impl is split into one if constexpr (BNXT) {...} else {...} so each
provider path is self-contained; shared SQ-space waits move into
waitSqSpace<PrvdType>.

Also migrate test_gda_warp_aggregate to the ccoUniqueId ccoCommCreate
overload (#411's test predated the bootstrap-API change and used the
removed application::BootstrapNetwork overload).

Verified on BNXT: 15 cco tests pass single-node; put/get/signal/
warp_aggregate + multiprocess pass cross-node (2-node, 16 ranks); GDA
benchmarks saturate line rate (~49 GB/s).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ringDoorbellOrdered keeps the dbTouchIdx wait-for-turn (per-QP ordering) but
rings per peer-group instead of per lane:

- put/get/putValue group active lanes by peer via a __ballot turn loop only in
  the WarpDefault+CoopThread path; each peer reserves contiguously and the group
  leader rings one doorbell (new LeaderOnly template path). WarpAggregate /
  CoopWarp / CoopBlock are a single group and skip the loop.
- Unify the BNXT/PSD anti-coalescing lane-walk (shared dbrAddr/UAR) into
  ringDoorbellWalk<PrvdType>, used by ringDoorbellOrdered's multi-lane path and
  flushAsyncImpl. This fixes a missing walk on BNXT flush: a multi-peer flush
  could drop coalesced doorbells and hang.
- Drop __syncwarp from the lane-walk. AMD wavefronts are lock-step, so per-lane
  predication already orders the stores; __syncwarp was also a deadlock (a lane
  past its turn waited on lanes still spinning in wait-for-turn).

benchmark/cco p2p_put_bw / p2p_get_bw drop ccoGdaOptFlagsAggregateRequests: a
per-op doorbell is now safe in thread/warp scope, and put's waitSqSpace drains
the CQ as the SQ fills, so the deferred-doorbell SQ overflow that hung those
scopes is gone.

Verified on BNXT: all cco GDA tests pass single-node + cross-node (2-node, 16
ranks); p2p bw saturates ~49 GB/s (line rate) across block/warp/thread scopes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The bw kernels split the total size across cooperative units — one WQE /
message per unit: block scope = one per block, warp = one per wavefront,
thread = one per thread. Previously the table only showed the total size, so
it was unclear how big each actual message was or how many pieces the total
was cut into.

PrintPerfTable now derives units from scope/grid/block/warpSize, prints
units=N in the header, and adds a "msg" column (size / units) — the bytes one
WQE carries in that scope. E.g. 4MB total: block → 32 units × 128KB,
warp → 128 × 32KB, thread → 8192 × 512B, which directly explains the bandwidth
differences between scopes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
-s thread_agg = thread scope (one WQE per thread) with WarpMode =
ccoGdaWarpAggregate, so the warp's same-peer lanes post as one aggregated batch
instead of the default per-peer __ballot grouping. Bandwidth kernels only
(ibgda_*_bw templated on WarpMode); latency uses one CoopBlock issuer so it
falls back to thread behavior.

On BNXT p2p, thread_agg matches thread within noise: after the per-peer doorbell
grouping, the WarpDefault path already aggregates same-peer warp lanes into one
batch/doorbell, so explicit WarpAggregate adds no measurable bandwidth — it only
skips the __ballot group discovery.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mpps = WQEs/messages issued per second = GB/s * 1e3 * units / size, computed
from existing table data. It exposes the per-WQE issue-rate ceiling: at small
messages the rate is flat (~115 Mpps on BNXT) and bandwidth = rate * msg, while
large messages are bandwidth-bound (line rate, low Mpps). Bandwidth tables only;
latency is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The GDA post sub-mode only takes effect under ccoCoopThread and the work unit
is per-thread, so the "Warp" naming was misleading. Rename:
  ccoGdaWarpMode      → ccoGdaThreadMode
  ccoGdaWarpDefault   → ccoGdaThreadIndependent
  ccoGdaWarpAggregate → ccoGdaThreadAggregate
plus the WarpMode template param, the test file/kernels, and bench help text.
ccoCoopWarp and physical-warp references (lane id, warp size) are unchanged.

Also condense the oversized comment blocks added by the doorbell-grouping work
down to their essential rationale.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jhchouuu jhchouuu merged commit 20cd0dc into dev/cco Jun 24, 2026
@jhchouuu jhchouuu deleted the jiahzhou/cco-gda-doorbell-bnxt-psn branch June 24, 2026 03:34
@jhchouuu jhchouuu changed the title perf(cco): BNXT GDA per-packet PSN + per-peer doorbell grouping; bench enhancements feat(cco): BNXT GDA per-packet PSN + per-peer doorbell grouping Jun 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant