Skip to content

lane core: several queued prompts in one pass (prefill_many, addStreams, the lane host admitting together) - #853

Closed
BobClawblaw wants to merge 10 commits into
ashhart:mainfrom
BobClawblaw:pr/lane-host-vision
Closed

BobClawblaw wants to merge 10 commits into
ashhart:mainfrom
BobClawblaw:pr/lane-host-vision

Conversation

@BobClawblaw

@BobClawblaw BobClawblaw commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Several queued prompts in one pass (lane core)

Since 1.0.12, main already carries most of what this PR first brought, so it is down to the one piece main lacks:

  • Images and video: core/picture, the server's images/videos/media_fetch, and the image fields on requests. I dropped this branch's vision_inputs, qwen_image, glm_image and tf_video.
  • Two-rank serving: --tp/--rank/--master, engines.follow for ranks above 0, and room set by the smallest rank. I dropped this branch's versions.
  • Prompt-cache lifetimes: main's borrowers (an entry a lookup holds is never evicted, and a dead one leaves lookups at once and storage at a safe boundary) do what this branch's pins did. Jobs set up together each borrow their entry, so none evicts another's.

What remains: batched prompt passes.

  • Backend.VTable.prefill_many(ss): a backend that prefills several prompts in one pass gets them together (up to 16), and each stream opens as after its own prefill. Returning false or an error leaves none prefilled, and the lane core then runs each stream alone. One stream's refusal, or no room for all of them, never takes the others down.
  • Engine.addStreams and Engine.batchesPrompts.
  • LaneHost.admitOne is split into takeJob (off the queue, under the lock), setup (the stream) and launch (warm pass, lone driver, fill queue or its own pass). Admission one at a time behaves as before. When the backend batches prompts, none fill by chunks, and two or more requests wait with two lanes free, admit.many takes, sets up and prefills them together. Warm and lone ones launch as before.
  • cuda_bound.zig and the --record wrapper (recorder.zig) forward prefill_many. The recorder records each prompt as after its own prefill.

No family implements prefill_many yet; GLM's two-rank family (#855) will in a follow-up.

Checks

zig build test with four new lane-host tests on the fake's batched backend (Fake.batched()), each reply checked against the target's own continuation:

  • four queued requests share one prompt pass;
  • six requests on four lanes: the free lanes' prompts in one pass, the rest after;
  • a backend with room for two: the four-stream pass is refused, they go one at a time, and a later pass takes only as many as fit;
  • one request the backend refuses (sampled) fails alone; the other three's replies are kept.

test-kernel-contract, test-golden, test-cuda-host, zig build native (CUDA, sm_121), zig fmt --check and the lean check pass.

…wer: batched prompt passes (prefill_many, addStreams), a backend's refusals for a memory guard, follow() for a tensor-parallel rank 1, shared-pool admission fields, image and video inputs for the native server (vision_inputs, media_fetch, qwen_image, stb_image)
…cel; lean rule and zig fmt

setup() returned cancel()'s true for a background warm pass that yields to a newer request, so the caller
launched the job cancel() had just finished (SEGV in lane_host_warm_test). It now returns false, as for a drop.

Comments one line each; lean_check skips zig/vendor/ (stb_image.h, as on ashhart#726). lane_host.zig and
lanes/engine.zig stay under 600 lines: the batched prompt pass moves to lane_host_admit.zig (many, one) and
lanes/open.zig (addStreams, adoptPrefilled), aliased where they were.
…rozen words (the errors/content-image golden)
@BobClawblaw

Copy link
Copy Markdown
Contributor Author

CI fix. zig was failing on three things, not only lean.

  • A crash in zig build test, now fixed in ef73ec3d. lane_host_warm_test ("a warm pass waits for a quiet engine...") segfaulted on every run. setup() kept admitOne's return h.cancel(job) for a background warm pass that yields to a newer request. cancel() finishes the job and returns true, so the caller went on to launch() the job it had just finished. setup() now returns false after the cancel, as it does for a drop. The test passes 3 of 3 runs here, and it failed 3 of 3 before.
  • test-golden, fixed in cc5d9d16. Once the tests ran, errors/content-image differed from the frozen answers: a server without --vision now said "image and video inputs need a server started with --vision". It now refuses with the frozen words, as Native image input: images from a request's image parts, prepared before admission; GLM-5.3-Flash reads them on Metal #598 does. That gives 309/319 equal, 0 unexpected.
  • Lean.
  • zig fmt on five files.

Locally: zig build test, test-golden, fuzz-cortheon and lean_new.py (0 new) pass. Not run on the GB10 pair, and no served run of the vision inputs after the change.

…nsorfold-native takes memcpy from libSystem again (zig build test on macOS)
@ashhart

ashhart commented Oct 15, 2026

Copy link
Copy Markdown
Owner

Hello @BobClawblaw,

Thank you for the lane-host hooks for two-rank families. Several streams in one pass (engine.zig:119), follow for rank 1 (cuda.zig:257), two_ranks (cuda.zig:352), setStreams and setRoom (cuda.zig:396, cuda.zig:397), and the vision input check (vision_inputs.zig:122) move in with #804, which is the GLM CUDA family.

JPEG and PNG stay on the pinned libjpeg-turbo. Please drop zig/vendor/stb and stop compiling it (vision.zig:7). refusedFn is unused (fake.zig:246), so that function needs to be wired or removed.

admitMany sets up several jobs before the backend runs them (lane_host.zig:411, lane_host.zig:424). setup keeps a saved state that is only safe until that job's own pass (lane_host.zig:317). The next job's reserve can evict it (prompt_cache.zig:279, prompt_cache.zig:293), and the first restore then reads freed memory. Pin each setup job's entry until its restore. No family installs prefill_many yet (engine.zig:113), so nothing serves this path today. Please fix it before the hook moves.

Thank you again.

…eports; images wait for the shared decoder; no refused hook

- prompt_cache: Entry.pins, Store.pin/unpin. victimBut passes pinned entries over, so a later job's lookup in
  admit.many (or a keep during the batched pass) no longer frees a state an earlier job has yet to restore; a keep
  with nothing evictable fails instead of unwrapping null. LaneHost.setup pins, reported and requeue unpin.
- vision: zig/vendor/stb dropped and no longer compiled. qwen_image.decode refuses by name (NoDecoder) until the
  shared runtime decoder (pinned libjpeg-turbo) lands; lean_check's vendor exemption goes with it.
- lanes: Backend.VTable.refused, Engine.refused, cuda_bound's forwarding and the fake's stray refusedFn removed;
  nothing consumed them.
@BobClawblaw

Copy link
Copy Markdown
Contributor Author

Hello @ashhart,

Thank you. Pushed in 9e6dfcd:

  • stb is gone and no longer compiled. qwen_image.decode refuses images by name until the shared libjpeg-turbo decoder lands.
  • refusedFn is removed, along with Backend.VTable.refused, Engine.refused and its cuda_bound forwarding, since nothing consumed them.
  • Each setup job's kept entry is pinned until its restore reports. Eviction passes pinned entries over, so a later job's lookup or keep can't free one, and a keep with nothing left to evict fails instead. A new prompt_cache test checks this.

zig build test, the engine seam tests and the CUDA build pass.

@ashhart

ashhart commented Oct 15, 2026 •

Copy link
Copy Markdown
Owner

Thank you, @BobClawblaw, for the cleanup and the restore pinning. At 9e6dfcd4, the pin, both victim selection passes and RestoresPending close ordinary competing eviction.

One should-fix remains at zig/src/core/prompt_cache.zig:376 and line 380, called from zig/src/core/lane_host.zig:88 and line 91. Two admitted jobs pin the same entry E. The first restore fails and falls back to a fresh prefill. After both passes finish, the first report unpins E once, then resumed(E, false) frees it despite the second pin, and the second report writes through freed memory in unpin.

Mark E invalid at once so new lookups miss it, and free it only when its last pin goes. The same rule applies to forget at prompt_cache.zig:320. Please add a two-pin regression that fails one restore and checks the other borrow survives until its release; the one-pin test does not cover this. It stays latent until a family installs prefill_many.

Posted by Ash's AI Assistant Synthena

…eed only at its last unpin; a job reports resumed before it unpins
@BobClawblaw

Copy link
Copy Markdown
Contributor Author

@ashhart Thank you. Fixed in 52b82fc5.

  • An entry removed while pinned is dead, not freed. remove drops it from the entries at once, so no lookup finds it again, and marks it dead. The last unpin frees it (prompt_cache.zig:162, :173). resumed(E, false), forget and clear all go through remove, so a failed restore or a forget can't free a state another admitted job still restores.
  • reported unpins after resumed (lane_host.zig:88). It used to unpin first, then read e.at and call resumed, which would read freed memory once the last unpin frees.
  • free takes the entry's bytes off held itself, so a dead entry's bytes stay charged until it actually goes. keep now charges held before appending, so its out-of-memory path frees a charged entry.

Two regressions in prompt_cache_test.zig:

  • Two jobs pin one entry and the first restore fails: lookups miss it, the state stays alive and charged with one pin left, and the second job's unpin frees it.
  • forget on a pinned entry: lookups miss it, and it lives until its unpin.

With the old prompt_cache.zig both abort on freed memory. With the fix both pass. On an M5 Ultra, zig build test passes 162/162 steps (1,994 of 2,002 tests, 8 skipped), zig fmt --check is clean, and the lean check reports 0 new problems. CI is green.

BobClawblaw added a commit to BobClawblaw/TensorFold that referenced this pull request Oct 15, 2026
ashhart#853's host builds each family's options from F.Options; with it, image input
from ashhart#885 reaches the 35B-A3B unchanged.

Claude-Session: https://claude.ai/code/session_019t9cKWEuJaAitqMuN9rYFE
BobClawblaw added a commit to BobClawblaw/TensorFold that referenced this pull request Oct 15, 2026
The ashhart#853 merge removed learnBytes (ashhart#836 reads learn_bytes in place); its doc line
stayed above toGib.

Claude-Session: https://claude.ai/code/session_019t9cKWEuJaAitqMuN9rYFE
BobClawblaw added a commit to BobClawblaw/TensorFold that referenced this pull request Oct 15, 2026
…d a trailing blank line

- vision_inputs opens libtfvideo through sys.DynLib (LoadLibraryW on Windows, as
  tfvideo.dll): std.DynLib has no Windows. media_fetch's connect is Linux socket
  calls; a Windows server refuses image URLs by name. ashhart#836 builds the server's
  tests on Windows and ashhart#853 brought both, so they met here.
- tf-qwen35-cuda's header and two comments within one line and 120 columns.
- docs/vision.md ends in one newline (git diff --check).

Claude-Session: https://claude.ai/code/session_019t9cKWEuJaAitqMuN9rYFE
BobClawblaw added a commit to BobClawblaw/TensorFold that referenced this pull request Oct 15, 2026
ashhart#853's host builds each family's options from F.Options; with it, image input
from ashhart#885 reaches the 35B-A3B unchanged.
@ashhart

ashhart commented Oct 15, 2026

Copy link
Copy Markdown
Owner

Thank you, @BobClawblaw, for covering both failed restore and forget while another borrower still holds the entry.

At 52b82fc, zig/src/core/prompt_cache.zig:162 removes the entry from lookup immediately, while the final unpin releases its memory. The held-byte charge lasts until that release. zig/src/core/lane_host.zig:88 also keeps the pin through resumed use, and the append failure balances its charge.

The lifetime finding is closed in source. This is ready for the cache landing checks, including the two-borrower regressions.

Posted by Ash's AI Assistant Synthena

…h (core/picture, server images and videos, media_fetch), its two-rank serving (--tp/--rank, engines.follow, room by the smallest rank) and the prompt cache's borrowers replace this branch's; the batched prompt passes come back on main's lane host next
…ill_many (Engine.addStreams; the lane host takes, sets up and launches each job as before and prefills the shared-pass ones together); a pass that errs or has no room leaves none prefilled and each stream goes alone; the CUDA and recorder wrappers forward it; the fake's batched backend and four host tests
@BobClawblaw BobClawblaw changed the title lane core and native CUDA host for two-rank families: batched prompt passes, refusals, follow(), image and video inputs lane core: several queued prompts in one pass (prefill_many, addStreams, the lane host admitting together) Oct 16, 2026

@cwschroeder cwschroeder left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed b416ec8 on main 46a08c18. I found one test-backend contract mismatch and prepared a small patch with additional CPU coverage: https://gist.github.com/cwschroeder/169d1f6ec8254a7fc8e696b7fc78b118.

In lanes/fake.zig:92, an error after prefill inserts the current lane leaves that lane behind: the cleanup visits only earlier participants. Direct callback tests for Cancelled and Yielded both fail on the unchanged implementation (expected 1, found 2, with one unrelated lane already live). Including the failing participant in the cleanup fixes both. This is a Fake contract defect; the solo fallback can clean it up later, so this does not establish a persistent serving leak.

The patch also checks:

  • Cancel and yield at the first, middle and last participant, preserving the unrelated lane and allowing solo retries.
  • A successful batch followed by one first-token or draft error: the other replies retain their expected tokens and all lane state is released by the host.
  • Recorded around the batched backend, including batch refusal and solo fallback. Recorded and unrecorded replies match for each configuration; each stream's token, position and feature files match its own context. Removing the batch prompt recording makes the new test fail.

Local Zig 0.17.0 validation at patch commit 4094e022 passes: 175/175 host and 61/61 recorder tests in Debug and Fast, plus the full No-GPU workflow commands, whole-tree formatting and lean (zero new findings). The PR's four current-head GitHub checks separately pass; the offered patch has local validation only.

Astra reviewed the patch with no remaining material source finding. These are CPU host/recorder tests. GPU rollback, model parity and performance have not been run. The family callback still owns complete rollback and completion of queued device work before returning false or an error.

@BobClawblaw

Copy link
Copy Markdown
Contributor Author

@cwschroeder Thank you for the patch and the clear write-up. Taken in ae4461d8, with you as co-author.

  • The fix: fake.zig's prefill_many cleanup now includes the failing participant. Without it, both new rollback tests fail with expected 1, found 2, as you found. With it, the host tests pass 175/175 and the recorder tests 61/61.
  • Scope: only the fake implements prefill_many on this branch; recorder.zig and native/cuda_bound.zig forward it, and no family has its own yet. So, as you said, it's a test-backend contract fix, not a serving leak. A family that implements prefill_many will need the same rule: none of the passed streams may be left prefilled on an error, the failing one included.
  • Checks (M5 Ultra, Zig 0.17.0): zig build test test-golden pass, zig fmt --check clean, git diff --check clean, and lean_check.py reports 517 problems, the same as main at 46a08c18. No GPU or model run, since only test code and the fake backend change.

BobClawblaw added a commit to BobClawblaw/TensorFold that referenced this pull request Oct 16, 2026
…) into pr/glm-flash-cuda: the glm_cuda family leaves; DFlash2, history-copy drafts, the vision tower and the EXL3 routed experts move into families/glm commit by commit, its kept states are main's
@ashhart ashhart mentioned this pull request Oct 17, 2026

@cwschroeder cwschroeder left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rechecked adopted commit ae4461d8 with Zig 0.17.0 on macOS arm64. The actual CPU host root passes 175/175 tests and recorder_test.zig passes 61/61. In a temporary source copy, restoring only the old exclusive cleanup makes both new Cancelled/Yielded rollback regressions fail (expected 1, found 2); the tracked worktree stays unchanged. Whole-tree format and patch whitespace pass. All four current-head GitHub checks are green.

Astra found no material issue in this adoption delta. This closes my Fake rollback finding and confirms the added host/recorder assertions. It remains test-backend coverage: no family implements prefill_many here, and this is no GPU rollback, model-parity or performance qualification.

@ashhart

ashhart commented Oct 17, 2026

Copy link
Copy Markdown
Owner

Thanks @BobClawblaw and @cwschroeder for the failing-participant rollback control and its credited fix. The distinction is right: ae4461d fixes the fake backend's contract, rather than demonstrating a serving leak.

Every real batched-prompt implementation must leave all passed streams clean on failure, including the participant that failed. We retain that requirement in the maintained family integration alongside slot ownership, media state and prompt-cache lifetimes. The host and recorder results cover their stated paths; GPU failures and rank-wide cleanup still need the final family's device checks. This remains shared lane admission, with ordinary cache reuse preserved.

Posted by Ash's AI Assistant Synthena

ashhart pushed a commit that referenced this pull request Oct 18, 2026
ashhart pushed a commit that referenced this pull request Oct 18, 2026
…-cuda: the glm_cuda family leaves; DFlash2, history-copy drafts, the vision tower and the EXL3 routed experts move into families/glm commit by commit, its kept states are main's
ashhart added a commit that referenced this pull request Oct 18, 2026
… prompts in one pass for a backend that batches them

The pull request's newest head merges 1.0.12 in, so it merges cleanly here. Its commits are copies without
zig/vendor/stb (author, committer and message byte for byte; each tree differs from the original only there), so the
vendored decoder is in no tree of this history. It adds prefill_many to the lanes backend, Engine.addStreams and the
lane host's admission of several queued jobs in one prompt pass, with a failed pass leaving none prefilled. No backend
here sets prefill_many, so every family admits one job at a time as before; the fake backend's tests cover the path.
ashhart added a commit that referenced this pull request Oct 18, 2026
…s and trees), and a platform layer for Windows

The pull request's head is rebased on 1.0.12 by its author, who resolved what the earlier landing's thirteen conflicts
held; checked here: the request log stays owner-only (its test skips the mode on Windows), prefill_attention.cu keeps
the four instantiations, and a family's stream buffers are still reserved once the count is known (now through the
drafter wrapper's reserve). One conflict with #853, resolved keeping both: recorder_test.zig's planted link skips
without the privilege on Windows, and its target can be the batched one. The head's newest commits take 1.0.12's new
modules through the platform layer for Windows, keep a stream's recorder file off links, and move the docs to port
8888, which a later commit here puts back to 8080.
ashhart pushed a commit that referenced this pull request Oct 18, 2026
…iling blank line

- vision_inputs opens libtfvideo through sys.DynLib (LoadLibraryW on Windows, as
  tfvideo.dll): std.DynLib has no Windows. media_fetch's connect is Linux socket
  calls; a Windows server refuses image URLs by name. #836 builds the server's
  tests on Windows and #853 brought both, so they met here.
- tf-qwen35-cuda's header and two comments within one line and 120 columns.
- docs/vision.md ends in one newline (git diff --check).
ashhart added a commit that referenced this pull request Oct 18, 2026
…red decoder): Qwen's image tower on CUDA and M-RoPE rows in the CUDA forward

The pull request's head is unchanged, but it sits on #836's previous line and #853's vendored decoder, so its own
commits are cherry-picked here onto the rebased line, each under its author: the forward's image rows and M-RoPE
positions, the tower and --vision on the Qwen engine, the tool's vision and mrope checks, the tower's bounds and the
lean fixes. Its doc-comment removal finds the line already gone here. As in the earlier landing, the server side
(vision_inputs.zig and media_fetch.zig, which came with #853) keeps this tree's code, qwen35.cu keeps #849's embed8
beside the splice, and the forward embeds through #849's embed before the splice. What the line adds equals what the
earlier landing's merge of this head added.
ashhart added a commit that referenced this pull request Oct 18, 2026
…re/qwen_vl, the engine's Vision)

#885's tower read its own vision_config and took #853's image type (patches and a grid, placeholders found by
scanning) from a server path this tree does not have. The family now takes what the server sends every image
family: --vision's limits at open, and requests' images as lanes.stream.Image (pixels, grid, prompt row, tokens).
- cuda_vision.zig: the tower's shape comes from core/qwen_vl's Config (the checkpoint's processor settings included),
  with this tower's own bounds (patch 16, temporal 2, merge 2, 48 x 48 positions, heads of 64 or 72, depth up to 32)
  and the text's interleaved M-RoPE sections 11, 11, 10 still checked. Vision holds the settings, the tower and the
  limits; its prepare is core/qwen_vl's (the server's decode, resize and patches, and the image's identity), at most
  one tower call's 4,096 tokens.
- cuda_vision_prompt.zig: placeholder checks and t, h, w positions are core/qwen_vl's Layout (the Metal 27B's),
  feature rows in prompt order; the tower still runs whole images in calls of at most 16,384 patches.
- cuda_native.zig: Options.vision is the limits, Loaded.vision the tower; open refusals are worded (explains_open).
- native/cuda_vision_offer.zig offers Qwen's processor, image token and markers (the template writes vision_start and
  vision_end itself) beside Nemotron Omni's.
- tf-qwen35-cuda vision runs picture files through core/qwen_vl and the tower twice (bit-equal), and compares the rows
  with float32 reference rows (relative L2, worst and mean, bounded), as tf-qwen-vision does on Metal.
ashhart added a commit that referenced this pull request Oct 18, 2026
…red decoder): Qwen's kept prompt states on CUDA, in pinned host memory

The pull request's head is unchanged but sits on #836's previous line and #853's vendored decoder, so its commits are
cherry-picked here onto the rebased line, each under its author: the family's kept states (cuda_reuse.zig) with
hostCacheBytes, the check of a kept state before its restore, and the tool's resume and rope-shift controls. As in the
earlier landing, its lane host, engine_api, server and image_key changes keep this tree's code, so three of its
commits (the cache key from #726, the server's image cache key, the lanes digest) add nothing here and are left out.
What the line adds equals what the earlier landing's merge of this head added.
ashhart added a commit that referenced this pull request Oct 18, 2026
ashhart added a commit that referenced this pull request Oct 18, 2026
… images and video, with #855 beneath it

The merged commits keep their authors' names, dates and messages with two changes: a login-only noreply address
becomes its author's id+login noreply, and no tree carries the stb_image decoder an early commit vendored and a later
one removed. The #853 commits beneath them are the ones the #853 merge landed without that decoder. Both sides keep
their kernel lists, launch records, test commands and GLM forward fields. The GLM host keeps this tree's open and
openRank split, with #976's image tower inside openRank and its _exit for a failed follower. The CUDA family options
take #976's video limits in cuda_options.zig, and the vision offer keeps Qwen's case and the wrapper rule beside
#976's video offer.
@ashhart

ashhart commented Oct 18, 2026

Copy link
Copy Markdown
Owner

Thank you, @BobClawblaw, for batching queued prompts and the failed-pass rollback checks.

We carried your work into 1.1.0 in 1f5631f, retaining your authorship while replaying the history without the vendored decoder. A backend implementing prefill_many can take several queued prompts in one pass, with failed batching and later token/draft errors covered by the fake backend.

No served family enables it in 1.1.0. The GLM batched-prompt follow-up is for 1.1.1. We are closing this PR because the credited replay has different commit IDs.

Posted by Ash's AI Assistant Synthena

@ashhart ashhart closed this Oct 18, 2026
BlivionIaG pushed a commit to BlivionIaG/TensorFold that referenced this pull request Oct 20, 2026
… queued prompts in one pass for a backend that batches them

The pull request's newest head merges 1.0.12 in, so it merges cleanly here. Its commits are copies without
zig/vendor/stb (author, committer and message byte for byte; each tree differs from the original only there), so the
vendored decoder is in no tree of this history. It adds prefill_many to the lanes backend, Engine.addStreams and the
lane host's admission of several queued jobs in one prompt pass, with a failed pass leaving none prefilled. No backend
here sets prefill_many, so every family admits one job at a time as before; the fake backend's tests cover the path.
BlivionIaG pushed a commit to BlivionIaG/TensorFold that referenced this pull request Oct 20, 2026
…2 drafts and trees), and a platform layer for Windows

The pull request's head is rebased on 1.0.12 by its author, who resolved what the earlier landing's thirteen conflicts
held; checked here: the request log stays owner-only (its test skips the mode on Windows), prefill_attention.cu keeps
the four instantiations, and a family's stream buffers are still reserved once the count is known (now through the
drafter wrapper's reserve). One conflict with ashhart#853, resolved keeping both: recorder_test.zig's planted link skips
without the privilege on Windows, and its target can be the batched one. The head's newest commits take 1.0.12's new
modules through the platform layer for Windows, keep a stream's recorder file off links, and move the docs to port
8888, which a later commit here puts back to 8080.
BlivionIaG pushed a commit to BlivionIaG/TensorFold that referenced this pull request Oct 20, 2026
…d a trailing blank line

- vision_inputs opens libtfvideo through sys.DynLib (LoadLibraryW on Windows, as
  tfvideo.dll): std.DynLib has no Windows. media_fetch's connect is Linux socket
  calls; a Windows server refuses image URLs by name. ashhart#836 builds the server's
  tests on Windows and ashhart#853 brought both, so they met here.
- tf-qwen35-cuda's header and two comments within one line and 120 columns.
- docs/vision.md ends in one newline (git diff --check).
BlivionIaG pushed a commit to BlivionIaG/TensorFold that referenced this pull request Oct 20, 2026
…e vendored decoder): Qwen's image tower on CUDA and M-RoPE rows in the CUDA forward

The pull request's head is unchanged, but it sits on ashhart#836's previous line and ashhart#853's vendored decoder, so its own
commits are cherry-picked here onto the rebased line, each under its author: the forward's image rows and M-RoPE
positions, the tower and --vision on the Qwen engine, the tool's vision and mrope checks, the tower's bounds and the
lean fixes. Its doc-comment removal finds the line already gone here. As in the earlier landing, the server side
(vision_inputs.zig and media_fetch.zig, which came with ashhart#853) keeps this tree's code, qwen35.cu keeps ashhart#849's embed8
beside the splice, and the forward embeds through ashhart#849's embed before the splice. What the line adds equals what the
earlier landing's merge of this head added.
BlivionIaG pushed a commit to BlivionIaG/TensorFold that referenced this pull request Oct 20, 2026
…re/qwen_vl, the engine's Vision)

ashhart#885's tower read its own vision_config and took ashhart#853's image type (patches and a grid, placeholders found by
scanning) from a server path this tree does not have. The family now takes what the server sends every image
family: --vision's limits at open, and requests' images as lanes.stream.Image (pixels, grid, prompt row, tokens).
- cuda_vision.zig: the tower's shape comes from core/qwen_vl's Config (the checkpoint's processor settings included),
  with this tower's own bounds (patch 16, temporal 2, merge 2, 48 x 48 positions, heads of 64 or 72, depth up to 32)
  and the text's interleaved M-RoPE sections 11, 11, 10 still checked. Vision holds the settings, the tower and the
  limits; its prepare is core/qwen_vl's (the server's decode, resize and patches, and the image's identity), at most
  one tower call's 4,096 tokens.
- cuda_vision_prompt.zig: placeholder checks and t, h, w positions are core/qwen_vl's Layout (the Metal 27B's),
  feature rows in prompt order; the tower still runs whole images in calls of at most 16,384 patches.
- cuda_native.zig: Options.vision is the limits, Loaded.vision the tower; open refusals are worded (explains_open).
- native/cuda_vision_offer.zig offers Qwen's processor, image token and markers (the template writes vision_start and
  vision_end itself) beside Nemotron Omni's.
- tf-qwen35-cuda vision runs picture files through core/qwen_vl and the tower twice (bit-equal), and compares the rows
  with float32 reference rows (relative L2, worst and mean, bounded), as tf-qwen-vision does on Metal.
BlivionIaG pushed a commit to BlivionIaG/TensorFold that referenced this pull request Oct 20, 2026
…e vendored decoder): Qwen's kept prompt states on CUDA, in pinned host memory

The pull request's head is unchanged but sits on ashhart#836's previous line and ashhart#853's vendored decoder, so its commits are
cherry-picked here onto the rebased line, each under its author: the family's kept states (cuda_reuse.zig) with
hostCacheBytes, the check of a kept state before its restore, and the tool's resume and rope-shift controls. As in the
earlier landing, its lane host, engine_api, server and image_key changes keep this tree's code, so three of its
commits (the cache key from ashhart#726, the server's image cache key, the lanes digest) add nothing here and are left out.
What the line adds equals what the earlier landing's merge of this head added.
BlivionIaG pushed a commit to BlivionIaG/TensorFold that referenced this pull request Oct 20, 2026
…) into pr/glm-flash-cuda: the glm_cuda family leaves; DFlash2, history-copy drafts, the vision tower and the EXL3 routed experts move into families/glm commit by commit, its kept states are main's
BlivionIaG pushed a commit to BlivionIaG/TensorFold that referenced this pull request Oct 20, 2026
…xperts, images and video, with ashhart#855 beneath it

The merged commits keep their authors' names, dates and messages with two changes: a login-only noreply address
becomes its author's id+login noreply, and no tree carries the stb_image decoder an early commit vendored and a later
one removed. The ashhart#853 commits beneath them are the ones the ashhart#853 merge landed without that decoder. Both sides keep
their kernel lists, launch records, test commands and GLM forward fields. The GLM host keeps this tree's open and
openRank split, with ashhart#976's image tower inside openRank and its _exit for a failed follower. The CUDA family options
take ashhart#976's video limits in cuda_options.zig, and the vision offer keeps Qwen's case and the wrapper rule beside
ashhart#976's video offer.
BlivionIaG pushed a commit to BlivionIaG/TensorFold that referenced this pull request Oct 20, 2026
BlivionIaG pushed a commit to BlivionIaG/TensorFold that referenced this pull request Oct 20, 2026
…) into pr/glm-flash-cuda: the glm_cuda family leaves; DFlash2, history-copy drafts, the vision tower and the EXL3 routed experts move into families/glm commit by commit, its kept states are main's
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.

3 participants