Skip to content

add RTX 4090 profile bundle + validation (Llama-3.1-8B, bf16, tp1) - #59

Open
Arifuzzamanjoy wants to merge 4 commits into
casys-kaist:mainfrom
Arifuzzamanjoy:feature/rtx4090-profile-bundle-fix
Open

add RTX 4090 profile bundle + validation (Llama-3.1-8B, bf16, tp1)#59
Arifuzzamanjoy wants to merge 4 commits into
casys-kaist:mainfrom
Arifuzzamanjoy:feature/rtx4090-profile-bundle-fix

Conversation

@Arifuzzamanjoy

Copy link
Copy Markdown

refs #58

adds compute-only kernel latency bundle for RTX 4090 and an end-to-end
vLLM vs simulation comparison, as discussed in the issue thread with @JaehongCS20.

what's included

  • profile bundle: dense.csv, attention.csv, per_sequence.csv under
    profiler/perf/RTX4090/meta-llama/Llama-3.1-8B/bf16/tp1/
  • cluster configs: single instance, tp2, multi-instance (PCIe gen4 x16)
  • bench run: 300 requests, sharegpt workload, vLLM 0.19.0
  • validation: summary.txt + throughput/latency/requests plots

host details (vast.ai)

  • GPU: NVIDIA GeForce RTX 4090, 24GB GDDR6X
  • power limit: 450W (stock, no throttling)
  • driver: 580.95.05, CUDA 12.8
  • vLLM: 0.19.0, bfloat16, tp=1
  • measurement iterations: 3
  • SKIP_SKEW=1 per maintainer guidance

validation results

Metric                           vLLM         Sim     Diff%
TTFT Mean                     58015.4      7245.8    -87.5%
TPOT Mean                        34.6        94.7   +173.5%
Latency Mean                  80550.9     68671.6    -14.7%

errors are large. TTFT is massively underestimated by the simulator,
TPOT is overestimated. end-to-end latency is closer (~15%) because
the errors partially cancel. this matches what you described in the
issue thread — attention kernels on newer architectures producing
bigger gaps than the earlier RTXPRO6000 experiments.

all profile metadata and logs are retained in the PR. happy to dig
into which kernel category drives the TTFT gap if that's useful.

deferred

  • skew sweep (SKIP_SKEW=1, follow-up PR after reviewing bucket axes on Ada)
  • RTX 3090 / A5000 bundles (separate PRs)
  • additional models beyond Llama-3.1-8B

- fix npu_mem.mem_size 128 -> 24 in rtx4090_single_instance.json
- revert unrelated uv pip change in scripts/compile.sh
- remove redundant commented MODEL line in profile.sh
- enrich host_metadata.txt with full profiling environment
- accurate commit history (bench/validation not yet included)

Refs casys-kaist#58
- real vLLM v0.19.0 serving benchmark: Llama-3.1-8B, TP=1, 300 requests
- validation comparison: real vLLM vs LLMServingSim simulation
- workload: sharegpt-llama-3.1-8b-300-sps10.jsonl

Refs casys-kaist#58
@JaehongCS20

Copy link
Copy Markdown
Collaborator

Thanks for the bundle and the validation run.

The profile data checks out. Replaying your bundle against the per-tick schedule
of your own vLLM run reproduces 100.0% of the measured GPU-busy time at
alpha=0, and attention shows no hidden per-sequence cost — at a fixed total KV
of 65,536 tokens it is flat across n_decode 16..256 (315-333 us). So the gap is
not in the kernel latencies.

It is tied to #40 instead — the scheduler's KV eviction behaviour under memory
pressure. On a 24 GB card an 8B bf16 model leaves ~9 GiB for KV (~74k tokens),
while a full batch at max_num_seqs 128 wants roughly twice that, so the
eviction path is exercised at any load. The earlier RTXPRO6000 experiments ran
with ~81 GiB of KV headroom and never reached it, which is why the gap shows up
here and not there.

To fix it properly we are replacing the radix tree with a port of vLLM's blocked
KV cache (per-tier block pool, chained block hashes, eviction as a side effect of
allocation) and aligning the scheduler with vLLM V1's two-phase schedule().

We will report back once the RTX 4090 numbers land in a sensible range, and then
refresh the validation summary in this PR. The profile bundle itself does not
need changes.

JaehongCS20 added a commit that referenced this pull request Aug 19, 2026
…ll-ISL gate

Naming: --gpu-memory-utilization / gpu_memory_utilization becomes
--npu-memory-utilization / npu_mem.mem_util. It was the only surface in
the repo that said GPU -- the cluster config says npu_mem 40 times and
num_npus 18 -- and the simulator models accelerators that are not GPUs.
The flag help names vLLM's --gpu-memory-utilization so the
correspondence is not lost.

Placement: the per-instance override now lives inside npu_mem as
mem_util, beside the mem_size it multiplies and matching its mem_*
siblings. Validated at load: a non-numeric value or one outside (0, 1]
is refused with a message saying it is a fraction, since mistyping 0.9
as 90 would silently size the cache 100x.

Admission gate: --reserve-full-isl (on by default, per-instance
reserve_full_isl) admits a request only if its whole sequence fits, not
merely its first chunk. Port of vLLM's scheduler_reserve_full_isl, True
there too, documented as preventing "over-admission and KV cache
thrashing with chunked prefill". allocate_slots' block arithmetic is
extracted into _num_blocks_to_allocate so the gate and the allocation
cannot drift apart -- two estimates disagreeing was the radix tree's
central defect.

Startup output: a KV Cache Initialization section between the input
config and the run loop, listing each instance's derived capacity:

  • Instance [0] : 54400 tokens / 3400 blocks (6.64 GiB/rank at util 0.90)

The utilization fraction alone does not tell you where memory pressure
will land; the token count does. It is per instance and only known once
the schedulers exist, so it cannot be a row in the input-config block.
Dropped that block's global utilization row, which would have lied as
soon as one instance overrode it. New logger helper print_heading()
centres a section title without drawing a second rule.

"▶ Starting simulation..." moves to just before the loop. It used to
print before config_builder, the prefix pools, the schedulers, the
controller and the router were built.

Docs: AGENTS.md gains the gate and npu_mem.mem_util; the KV-cache and
memory page is rewritten around the block pool, the capacity formula and
the gate; CONTRIBUTORS.md picks up #51, #53, #56, #57 and credits the
two reports that drove this work (#40's scheduler analysis, and #58/#59,
whose 24 GB profiling run was the first time the simulator saw real KV
pressure); the CHANGELOG says explicitly what replaced the radix tree
and that prefix caching's user-visible flags are unchanged.

bench/examples/configs/*.json state mem_util: 0.9 explicitly. At 96 GiB
those configs have 458k-617k tokens of KV, far past what the workload
wants, so the value is inert there and all three examples reproduce
their previous clocks exactly.
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.

2 participants