Bug
In the single-node branch of utils/process_result.py, num_gpus is computed as:
single_node_env = get_required_env_vars(['TP', 'EP_SIZE', 'DP_ATTENTION'])
tp_size = int(single_node_env['TP'])
...
num_gpus = tp_size * pp * pcp_size
(lines ~245-254 on main)
This has no data-parallel term. For a recipe that runs vLLM/SGLang with --tensor-parallel-size 1 --data-parallel-size N (or any other way of running N independent full-model replicas via internal DP), TP stays 1 and num_gpus comes out as 1 * pp * pcp_size regardless of N — even though N GPUs are actually running and total_token_throughput is the sum across all N replicas.
Result: tput_per_gpu, output_tput_per_gpu, and input_tput_per_gpu are all inflated by a factor of N for any single-node config that uses internal --data-parallel-size without also bumping TP/PP/PCP_SIZE to reflect the real GPU count.
Reproduction
Any single-node recipe/config matching this shape reproduces it:
--tensor-parallel-size 1
--data-parallel-size N (N > 1), driven by a value the recipe script keeps local to itself (e.g. a shell constant) rather than exporting as TP, PP, or PCP_SIZE
process_result.py's single-node branch then divides by num_gpus=1 instead of N
Related but distinct
PR #2168 fixed a similar-shaped bug in the multinode agentic sibling-client path (process_agentic_result.py's _gpu_shape()), where IS_MULTINODE/PREFILL_*/DECODE_* env vars weren't forwarded to a sibling container. That fix does not cover this single-node classic-DP case — process_result.py's single-node branch still has no data-parallel-size input at all.
Impact
Any published throughput/cost numbers for a single-node internal-DP config (DP replicas on one node, not disaggregated, not multinode) are systematically inflated by the DP factor. This silently skews cross-config comparisons (e.g. DP-replica configs looking better per-GPU than they really are) wherever this metric is charted or fed into a cost-per-token calculation.
I can propose a fix (read the real DP size and fold it into num_gpus) in a follow-up — filing this first to get the root cause on record.
Bug
In the single-node branch of
utils/process_result.py,num_gpusis computed as:(lines ~245-254 on
main)This has no data-parallel term. For a recipe that runs vLLM/SGLang with
--tensor-parallel-size 1 --data-parallel-size N(or any other way of running N independent full-model replicas via internal DP),TPstays1andnum_gpuscomes out as1 * pp * pcp_sizeregardless of N — even though N GPUs are actually running andtotal_token_throughputis the sum across all N replicas.Result:
tput_per_gpu,output_tput_per_gpu, andinput_tput_per_gpuare all inflated by a factor of N for any single-node config that uses internal--data-parallel-sizewithout also bumpingTP/PP/PCP_SIZEto reflect the real GPU count.Reproduction
Any single-node recipe/config matching this shape reproduces it:
--tensor-parallel-size 1--data-parallel-size N(N > 1), driven by a value the recipe script keeps local to itself (e.g. a shell constant) rather than exporting asTP,PP, orPCP_SIZEprocess_result.py's single-node branch then divides bynum_gpus=1instead ofNRelated but distinct
PR #2168 fixed a similar-shaped bug in the multinode agentic sibling-client path (
process_agentic_result.py's_gpu_shape()), whereIS_MULTINODE/PREFILL_*/DECODE_*env vars weren't forwarded to a sibling container. That fix does not cover this single-node classic-DP case —process_result.py's single-node branch still has no data-parallel-size input at all.Impact
Any published throughput/cost numbers for a single-node internal-DP config (DP replicas on one node, not disaggregated, not multinode) are systematically inflated by the DP factor. This silently skews cross-config comparisons (e.g. DP-replica configs looking better per-GPU than they really are) wherever this metric is charted or fed into a cost-per-token calculation.
I can propose a fix (read the real DP size and fold it into
num_gpus) in a follow-up — filing this first to get the root cause on record.