Skip to content

nemotron cuda: a host test counts the RADIO tower's passes in a lane prefill (follow-up to #1057) - #1109

Closed
plotarmordev wants to merge 2 commits into
ashhart:mainfrom
plotarmordev:feat/vision-encode-hook
Closed

plotarmordev wants to merge 2 commits into
ashhart:mainfrom
plotarmordev:feat/vision-encode-hook

Conversation

@plotarmordev

Copy link
Copy Markdown
Contributor

What this changes

A follow-up to #1057, as invited there, on that branch's head: Vision.test_encode is a test-only hook on Nemotron's CUDA Vision, shaped like Head.test_network in cuda_mtp.zig. It stands in for the RADIO tower pass in Vision.begin, so a host test can count encodes per request. The new test in cuda_vision_test.zig runs Cuda.prefillFn for a prompt with two images and checks that each image went through the tower once. With #1057's fix reverted, it finds each image encoded twice. Outside test builds the hook's type is void and its branch is comptime-false, so release code does not change.

Receipt

  • Environment, with the TensorFold commit, MLX or PyTorch version, machine and GPU, checkpoint and revision: this branch at 9bf16af, on nemotron cuda: a prompt pass with images runs the RADIO tower once, not twice #1057's head e2357b5 (main d46d17a). Zig 0.17.0, Linux aarch64, CPU only (CUDA_VISIBLE_DEVICES= for the host tests). No GPU work and no checkpoint. zig build native -Dsm=121 -Dnvcc=… -Dstrip=true was built from this branch and from e2357b5, each in its own checkout. The two binaries are the same size and differ in 14 bytes, all of them inside one embedded fatbin's nvcc-generated _INTERNAL_<hash>_12_glm_quant_cu names. nvcc derives those names from the source path, and the two checkouts were at different paths. zig build native -Dsm=121 -Dnvcc=… (unstripped) also builds and links.
  • Exactness, from tools/bench_concurrent.py --alone --serial or token_sha against "draft": false: n/a. No served code changes, and the release builds above match outside nvcc's path-derived names.
  • Decode speed before and after, from tools/bench_openai.py: n/a, for the same reason.
  • Prompt speed before and after: the cold first request's ttft_s from tools/bench_cache.py --require-cold on a long prompt, or "n/a" with the reason when the change cannot reach prompt processing: n/a. The hook is compiled into test builds only.
  • Tests run, with pass, fail and skip counts:
    • zig build test test-kernel-contract test-golden test-cuda-host with a fresh cache: 2456 of 2466 tests passed, 9 skipped and 1 failed. The failure was cortheon fuzz: every reader takes linear time on long inputs, a wall-clock bound in the server suite that this change does not reach. A second run passed it, and that binary's 428 of 428 tests passed.
    • test-golden: 306/319 equal to the frozen answers, 0 unexpected differences. test-kernel-contract: every step passed.
    • zig fmt --check build.zig zig and git diff --check: clean. tools/zig/lean_check.py: 503 problems here and 503 on e2357b5, 0 new (tools/zig/lean_new.py).
    • With cuda_lanes.zig restored to d46d17a (the second begin and its defer back), test-cuda-host fails only the new test: it expected { 1, 1 } encodes and found { 2, 2 }.
  • Not run, and why:
    • GPU: the change touches test builds only, and the stripped release binaries match as described above.
    • Metal: Vision is CUDA-only.
    • A prefill resumed from a kept prefix with images: the test starts at row 0. A restore needs reuse.restore's device copies, which this fixture does not fake.

Checklist

  • Every token still goes through the lane rounds. No serial path, and nothing that needs drafts off. (No served code changes.)
  • Drafted output equals "draft": false, a resumed prompt equals a fresh one, and concurrent equals solo. (No served code changes; the stripped release builds match outside nvcc's path-derived names.)
  • No precision traded for speed. If the bits change, the description says which sums change and why. (No sums change.)
  • A new or changed GPU kernel is registered with the kernel contract (docs/kernel-contract.md); each backend's SUMMARY line is in the receipt. (No kernel changed.)
  • Prompt processing is no slower than the last release. (Release builds compile no hook.)
  • The description says which platforms I ran, Metal M1 to M5 and CUDA, and which I could not.
  • New tests fail before the change, pass after it, and skip cleanly without their dependency. (With nemotron cuda: a prompt pass with images runs the RADIO tower once, not twice #1057's fix reverted, the test fails and finds two tower passes per image. It needs no GPU, so it never skips.)
  • Comments and docstrings are one line. No measurements or history in the source.
  • No personal data, machine names, internal hosts or local paths. No AI attribution lines.

…ot twice

The merge of ashhart#897 and ashhart#938 put a `Vision.begin` where Bolt's branch set up its image rows, after the kept-prefix
restore, and kept the one Super VL's images brought after the prompt-rows setup. The second ends the first pass and
encodes every image again, so each image request ran the tower twice before its first chunk. The first call stays.
…prefill

Vision.test_encode, a test-only hook like Head.test_network, stands in for the tower pass. A lane prefill with two images encodes each once; with the second Vision.begin ashhart#1057 removed, each went through twice. Release builds compile no hook.
@plotarmordev

Copy link
Copy Markdown
Contributor Author

Closing in favour of #1104, which adds the same encode hook on Vision and drives the lane prefill through it.

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