The dispatch kernel launches a different thread count depending on whether it builds the dedup map, and the smaller of the two silently caps the supported rank count at 96 — while planning.py declares and enforces R <= 128.
Line numbers are master @ 0f385f0.
The two thread counts
moonep/dispatch.py:113-115:
self.num_threads = (
96 + 32 * DEDUP_BUILDER_WARPS if build_dedup_map else 96
)
with DEDUP_BUILDER_WARPS = 4 (moonep/constants.py:17), so:
- fresh plan (
build_dedup_map=True) → 96 + 128 = 224 threads
- reused plan (
build_dedup_map=False) → 96 threads
That value is forwarded to cross_rank_barrier, which requires one thread per rank — moonep/_common.py:304:
assert num_threads >= num_ranks, (
"cross_rank_barrier requires blockDim.x >= num_ranks: "
f"num_threads={num_threads}, num_ranks={num_ranks}"
)
The assert is load-bearing rather than defensive: only threads with tid < num_ranks signal peers, so a thread count below R would silently fail to signal some ranks.
The conflict
moonep/planning.py:1282 declares the supported ceiling:
Nothing anywhere caps R at 96. So on the plan-reuse path any R in [97, 128] fails the cross_rank_barrier assert at cute.compile trace time, while the same configuration works on the fresh-plan path in the same run.
The reuse path is reachable from the public API — api.py:742-752 sets planning_args = None whenever a plan is passed, and api.py:618 derives build_dedup_map = planning_args is not None. benchmarks/bench_comm.py:244 exercises exactly this for the backward re-dispatch.
I checked the other cross_rank_barrier callers and none is below 96: combine 192/224 (combine.py:91-92), grad_reduce 160 (grad_reduce.py:53), planning 512, inter_rank_sync max(32, ceil(R/32)*32) with R <= 1024 (inter_rank_sync.py:86-89). dispatch_epilogue.py:63's num_threads = 64 is not a counterexample — it never calls cross_rank_barrier.
Severity
Low, deliberately. The failure is a loud compile-time AssertionError, not corruption, and no shipping NVLink domain exceeds 72 ranks, so nothing reachable today trips it. It is a latent inconsistency between two paths of the same kernel rather than a live break.
Filing it because the two declared ceilings disagree, and if R > 96 ever becomes real the failure will appear only on the plan-reuse path, which is the harder one to notice.
Suggested fix
Either raise the reuse-path launch to at least the planning ceiling, or lower the declared ceiling and document 96 as the real limit. If the 96 is a deliberate occupancy choice for the reuse path, a comment saying so at :113 would prevent the next reader concluding it's a typo.
One correction to something that might come up: constants.py:7 defines RANK_BITS = 7 (2^7 = 128), which looks like it documents the 128 ceiling — but grep -rn RANK_BITS returns only that definition, so it is dead and the ceiling rests solely on the planning.py:1282 assert.
Verification
The dispatch kernel launches a different thread count depending on whether it builds the dedup map, and the smaller of the two silently caps the supported rank count at 96 — while
planning.pydeclares and enforcesR <= 128.Line numbers are
master@0f385f0.The two thread counts
moonep/dispatch.py:113-115:with
DEDUP_BUILDER_WARPS = 4(moonep/constants.py:17), so:build_dedup_map=True) →96 + 128 = 224threadsbuild_dedup_map=False) → 96 threadsThat value is forwarded to
cross_rank_barrier, which requires one thread per rank —moonep/_common.py:304:The assert is load-bearing rather than defensive: only threads with
tid < num_rankssignal peers, so a thread count belowRwould silently fail to signal some ranks.The conflict
moonep/planning.py:1282declares the supported ceiling:Nothing anywhere caps
Rat 96. So on the plan-reuse path anyRin[97, 128]fails thecross_rank_barrierassert atcute.compiletrace time, while the same configuration works on the fresh-plan path in the same run.The reuse path is reachable from the public API —
api.py:742-752setsplanning_args = Nonewhenever a plan is passed, andapi.py:618derivesbuild_dedup_map = planning_args is not None.benchmarks/bench_comm.py:244exercises exactly this for the backward re-dispatch.I checked the other
cross_rank_barriercallers and none is below 96: combine 192/224 (combine.py:91-92), grad_reduce 160 (grad_reduce.py:53), planning 512,inter_rank_syncmax(32, ceil(R/32)*32)withR <= 1024(inter_rank_sync.py:86-89).dispatch_epilogue.py:63'snum_threads = 64is not a counterexample — it never callscross_rank_barrier.Severity
Low, deliberately. The failure is a loud compile-time
AssertionError, not corruption, and no shipping NVLink domain exceeds 72 ranks, so nothing reachable today trips it. It is a latent inconsistency between two paths of the same kernel rather than a live break.Filing it because the two declared ceilings disagree, and if
R > 96ever becomes real the failure will appear only on the plan-reuse path, which is the harder one to notice.Suggested fix
Either raise the reuse-path launch to at least the planning ceiling, or lower the declared ceiling and document 96 as the real limit. If the 96 is a deliberate occupancy choice for the reuse path, a comment saying so at
:113would prevent the next reader concluding it's a typo.One correction to something that might come up:
constants.py:7definesRANK_BITS = 7(2^7 = 128), which looks like it documents the 128 ceiling — butgrep -rn RANK_BITSreturns only that definition, so it is dead and the ceiling rests solely on theplanning.py:1282assert.Verification
master@0f385f0this session, clean working tree; swept everycross_rank_barriercaller for a lower ceiling.cute.compileat anyR, let aloneR > 96. The trace-time failure is inferred from the assert operating on twoConstexprints inside a@cute.jit, not observed.