diff --git a/packages/app/src/components/collectivex/known-support.ts b/packages/app/src/components/collectivex/known-support.ts index 91160894d..7a431126d 100644 --- a/packages/app/src/components/collectivex/known-support.ts +++ b/packages/app/src/components/collectivex/known-support.ts @@ -98,9 +98,9 @@ export const COLLECTIVEX_KNOWN_FOOTNOTES: Record { ); }); + it('prefers wire_byte_provenance when the artifact carries it', () => { + // A token-expert LL row moves one copy per (token, expert); its deduplicated + // byte_provenance is a lower bound (~34% low on nccl-ep LL EP8 at T=128), so + // rates must divide from the wire basis when present. + const dispatch = makeCollectiveXSeries({ rows: [{ wireBytesFactor: 1.5 }] }).points[0] + .components.dispatch; + expect(dispatch?.payload_data_rate_gbps_at_latency_percentile?.p50).toBeCloseTo( + ((400000000 * 1.5) / 8 / 417) * 1e-3, + 3, + ); + expect(dispatch?.payload_bytes).toBe(400000000 * 1.5); + }); + it('does not invent rates for zero-byte or unavailable components', () => { const zeroStage = makeCollectiveXSeries({ rows: [{ stageZeroBytes: true }] }).points[0] .components.stage; diff --git a/packages/db/src/collectivex/reader.ts b/packages/db/src/collectivex/reader.ts index b3f4fb6cc..42cd0fd1f 100644 --- a/packages/db/src/collectivex/reader.ts +++ b/packages/db/src/collectivex/reader.ts @@ -59,6 +59,17 @@ interface RawRow { token_rate_at_latency_percentile: CollectiveXPercentiles; components: Record; byte_provenance: Record; + /** + * Bytes the kernels actually move: per-(token, expert) for the low-latency layouts + * that do not rank-deduplicate (DeepEP/UCCL/NCCL LL), identical to `byte_provenance` + * everywhere else. Absent on artifacts written before the wire basis shipped — + * for those, LL rates derived from `byte_provenance` are a lower bound (~34% low + * on nccl-ep LL EP8 at T=128), never an overstatement. + */ + wire_byte_provenance?: Record< + string, + { activation_data_bytes: number; total_logical_bytes?: number } + >; } // KV shards report per-burst rows instead of per-ladder-token rows; the two @@ -200,8 +211,11 @@ function mapComponent( } function mapPoint(row: RawRow, ep: number): CollectiveXPoint { - const component = (name: string) => - mapComponent(row.components[name], row.byte_provenance[name], ep); + // Divide rates from the wire basis when the artifact carries it: for the LL layouts + // that move one copy per (token, expert), `byte_provenance` is rank-deduplicated and + // publishing a rate from it presented a lower bound as the wire bandwidth. + const provenance = row.wire_byte_provenance ?? row.byte_provenance; + const component = (name: string) => mapComponent(row.components[name], provenance[name], ep); return { tokens_per_rank: row.tokens_per_rank, global_tokens: row.global_tokens, diff --git a/packages/db/src/collectivex/test-fixture.ts b/packages/db/src/collectivex/test-fixture.ts index 39a121743..b523daff8 100644 --- a/packages/db/src/collectivex/test-fixture.ts +++ b/packages/db/src/collectivex/test-fixture.ts @@ -14,6 +14,8 @@ export interface RowOverrides { globalTokens?: number; stageUnavailable?: boolean; stageZeroBytes?: boolean; + /** Adds wire_byte_provenance at this multiple of byte_provenance (a token-expert LL row). */ + wireBytesFactor?: number; } export interface ShardOverrides { @@ -78,13 +80,29 @@ function makeRawRow(index: number, row: RowOverrides, worldSize: number): Json { if (!row.stageUnavailable) { byteProvenance.stage = bytes(row.stageZeroBytes ? 0 : 192381952); } - return { + const raw: Json = { tokens_per_rank: tokensPerRank, global_tokens: row.globalTokens ?? tokensPerRank * worldSize, token_rate_at_latency_percentile: percentiles(8_338_218), components, byte_provenance: byteProvenance, }; + if (row.wireBytesFactor !== undefined) { + const scaled = (entry: Json): Json => ({ + activation_data_bytes: + (entry as { activation_data_bytes: number }).activation_data_bytes * row.wireBytesFactor!, + total_logical_bytes: + ((entry as { total_logical_bytes?: number }).total_logical_bytes ?? 0) * + row.wireBytesFactor!, + }); + raw.wire_byte_provenance = Object.fromEntries( + Object.entries(byteProvenance as Record).map(([name, entry]) => [ + name, + scaled(entry), + ]), + ); + } + return raw; } function makeRawCase(options: ShardOverrides, caseId: string): Json {