Skip to content

dots: the image tower's weights on CUDA - #2769

Open
laudney wants to merge 2 commits into
ashhart:mainfrom
laudney:pr-dots-c
Open

laudney wants to merge 2 commits into
ashhart:mainfrom
laudney:pr-dots-c

Conversation

@laudney

@laudney laudney commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor
Before After
dots.mocr's vision_tower tensors on CUDA not read loaded as BF16 [n, k] matrices for cuBLASLt
fc1 and fc3 — stacked into one gate|up projection
The patch weight — flattened to 588 columns and zero-padded to 592, so its rows meet cuBLASLt's alignment
A failed load — drains its uploads before any buffer is freed
Served behavior text only unchanged: nothing opens the tower until piece d

What this changes

The tower's weights load on CUDA (zig/src/families/dots_mocr/cuda_tower_weights.zig). Every vision_tower tensor is consumed, the device bytes count the padding, and a failed load drains its uploads before it frees anything. No served path opens the tower in this piece.

Checks on this head

  • Head commit: f4550b060
  • Review fixes (Ash's 21:08 points) are new commits on this piece, listed above. On this head (Linux x86_64): zig build test-cuda-host, check-native-cuda-host 7/7, test-kernel-contract, zig fmt --check and git diff --check pass; lean 386 / 386, 0 new against piece b. On the GB10 at the stack's head cd1cb0baa: dots-image and dots-text (with --vision and text only) equal their pins; the projection check passes 24 of 24 and fails a planted value two BF16 steps off. The checks below ran on the earlier heads, whose code equals this head's but for these fixes.
  • Lean checker, python3 tools/zig/lean_check.py, on the base (cuda: a shared engine for dense decoders, with dots.mocr's text decoder on it #2673's head 05e5e5fdd) and on this head: 386 / 386, 0 new (also 0 new against piece b).
  • Tests run (Linux x86_64, no GPU):
    • zig build test-cuda-host: 378/378 steps, 0 failed (the test binaries this piece changes re-ran; the others are the parent's and passed there).
    • zig build test-cuda-dense-host: 33/33 passed, uncached. zig build test-dots-mocr-cuda-host: 14/14 passed, uncached.
    • zig build check-native-cuda-host: 7/7 steps. zig build test-kernel-contract: 32/32 steps, 0 failed. zig build compile-cuda-tests (the GB10 runner compiles): 10/10 steps.
    • zig fmt --check build.zig zig, git diff --check: pass.
  • CI: pending on this head.
  • zig build test test-golden (Linux x86_64) on the stack's top 6bb38b3a1: 662/665 steps, 8,692/8,760 tests passed, 67 skipped; the one failure is cuda_disk_test, whose write deadline fails on the base too under load.
  • Not run, and why: the GB10 device checks: the receipts of pieces d and e.

Receipt

n/a: no served path opens the tower in this piece. The exact device bytes (2,524,194,816) are pinned by a host test against a sparse checkpoint in piece d, where the tower uses these weights.

Checklist

  • The title and description match the head commit, including the receipt and the stack.
  • New tests fail before the change, pass after it, and skip cleanly without their dependency: its host tests (the tower's bytes, padRows, the upload drain, and the load's settle order through load on a sparse checkpoint) each fail with their check removed.
  • Comments and docstrings are one line. No measurements or history in the source.
  • No personal data, machine names, internal hosts or local paths in the diff or its commits. No AI attribution lines.

@ashhart

ashhart commented Nov 10, 2026

Copy link
Copy Markdown
Owner

Thanks @laudney, this reads cleanly: every tower tensor is consumed and the padded device bytes are counted. Two small things:

  • The checklist says this piece adds no test, but it adds three (the bytes, padRows and the drain). Could you correct that line?

  • The drain test calls settle() directly. If it's cheap, a test that also fails when the errdefer l.settle() in load is dropped or moved would pin the order. If that isn't practical without a device, a sentence saying so is enough.

  • Synthena (Ash's Agent)

@laudney
laudney force-pushed the pr-dots-c branch 2 times, most recently from 7bdb0cd to f4550b0 Compare November 11, 2026 08:14
@laudney

laudney commented Nov 11, 2026

Copy link
Copy Markdown
Contributor Author

Thanks, both are in:

  • The checklist line now names the piece's tests.
  • f4550b060: a host test runs load on a sparse checkpoint with a fake upload whose wait fails, and checks that the uploads settle before the buffers are freed. It fails if the errdefer l.settle() is dropped, and fails if it is registered before errdefer t.deinit().

@ashhart

ashhart commented Nov 11, 2026

Copy link
Copy Markdown
Owner

Thanks @laudney, both are in. The new load test fails with the settle removed, and with it registered before t.deinit(). Ready from our side.

  • Synthena (Ash's Agent)

The tower's tensors load as plain BF16 [n, k] matrices for cuBLASLt:
fc1 and fc3 stacked into one gate|up projection, and the patch weight
flattened to 588 columns and zero-padded to 592 so its rows meet the
library's alignment. Every vision_tower tensor is consumed, the device
bytes count the padding, and a failed load drains its uploads before
any buffer is freed.
The drain test called settle directly, so dropping the errdefer in
load, or registering it before the tower's own errdefer, would stay
green. A host test now runs load on a sparse checkpoint against a
fake device whose first upload's wait fails: the buffers must go only
after the context proved the copies done. The sparse checkpoint
helper moves to its own test file so the tower's tests can share it.
@ashhart

ashhart commented Nov 14, 2026

Copy link
Copy Markdown
Owner

Thanks @laudney: #2767 and #2768 are in. With them on main, this rebased cleanly onto it (now b3435d0, your two commits unchanged apart from the base), and it is back in the landing queue.

  • Synthena (Ash's Agent)

This branch has not been deployed

No deployments
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