Skip to content

prefill: batched unbuffered stager reads; close the experts.bin view once reads are unbuffered (port of #833) - #1323

Closed
malloc32 wants to merge 1 commit into
Niko1221:mainfrom
malloc32:pr/833-stager-reads
Closed

malloc32 wants to merge 1 commit into
Niko1221:mainfrom
malloc32:pr/833-stager-reads

Conversation

@malloc32

@malloc32 malloc32 commented Oct 7, 2026 •

Copy link
Copy Markdown

AI-written. This PR was prepared by an AI (Claude Opus 5.5, via Claude Code) at the submitter's request; the code, the port and the measurements were done by the AI on the submitter's machine, and the submitter reviewed it before opening.

Update 2026-10-07: rebased onto 0.1.40.2 (e8ca9af). The one conflict was the Stager's wait in src/prefill/prefill.cpp: the release's sleeping wait (stager_sleep(), Linux by default) now applies to each job of a claimed run, beside the batched reads.

What

A port of @adonizm's #833 onto the current main (it was closed by the history rewrite, not rejected). Two changes:

  1. The prompt path's stager claims runs of consecutive jobs and reads them with one read_direct batch (ExpertSource::copy_blobs), merging neighbouring blobs into requests of up to 32 MiB. STRATA_STAGER_BATCH (default 8 for file-backed blobs, 1 otherwise).
  2. Once the file tier reads unbuffered, the mapped view of experts.bin is closed (FileExpertSource::drop_mapping, Windows): while it is mapped, NTFS serves the unbuffered reads one at a time. STRATA_KEEP_MAPPING=1 keeps it.

Two fixes on the way: unmapped_ is declared on every platform (mapped_blob reads it outside the Windows block, so Linux did not compile), and copy_blobs asks resident_blob, which follows the exchange rotation (STRATA_EXCHANGE_ROTATE).

Measured

i7-12700K, 64 GB, 2x RTX 5060 Ti (layer split), IQ3_S, experts.bin on a Samsung 990 PRO, --resident-budget-gib 8, unbuffered reads: prompt 513 -> 623 tok/s at 8K, 962 -> 1,198 at 32K. Batching gives most of it; closing the view adds 4-5%. The original author's numbers: 1,261 -> 1,669 tok/s at 47.6K.

Not tested

Linux and HIP builds (the Linux fix was checked with a syntax-only compile).

🤖 Generated with Claude Code

…erts.bin view once reads are unbuffered

NTFS serves unbuffered reads of a mapped file one at a time (WD SN580: 2 MiB reads at QD32
2.35 GB/s mapped vs 3.57 GB/s unmapped). With the file tier unbuffered (--resident-budget-gib
or STRATA_UNBUFFERED_LOAD=1) the mapped view is only a fallback after startup, so it is closed
(STRATA_KEEP_MAPPING=1 keeps it). The prompt path's stager claims runs of consecutive jobs and
reads them with one read_direct batch (STRATA_STAGER_BATCH, default 8 for file-backed blobs).

RTX 5070 Ti, 32 GB RAM, IQ3_XXS, 47.6K prompt, --resident-budget-gib 18 --prefill auto:32768:
1260 -> 1370 tok/s (batch 8) -> 1669 tok/s (view closed).

Ported from Niko1221#833 onto the rewritten main. Two fixes on the way: unmapped_ is declared on every
platform (mapped_blob reads it outside the Windows block, so Linux did not compile), and
copy_blobs asks resident_blob, which follows the exchange rotation (STRATA_EXCHANGE_ROTATE).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@malloc32
malloc32 force-pushed the pr/833-stager-reads branch from b89e2ae to d3659bc Compare October 7, 2026 19:52
@Niko1221

Niko1221 commented Oct 8, 2026

Copy link
Copy Markdown
Owner

Thank you malloc32 for bringing @adonizm's #833 back onto the current tree. It is in 0.1.41 with adonizm's authorship kept, merged with the sleeping-wait stager code. On the RTX 5070 Windows PC (file tier) the prompt time fell 45-52% with identical tokens in 18 of 18 runs. STRATA_STAGER_BATCH and STRATA_KEEP_MAPPING=1 are as written. We measured on Windows only. Closing as ported.

@Niko1221 Niko1221 closed this Oct 8, 2026
mobile2machan added a commit to mobile2machan/Strata that referenced this pull request Oct 8, 2026
128 commits: batch-groups auto per stage, server listen backlog 256, the
NVIDIA short-prompt CPU share, batched prompt reads (Niko1221#1323), the tokenizer
cache, the engine stall watchdog (Niko1221#1317 Niko1221#1407), conversation-cache eviction
(Niko1221#1347), prompt buffers sharing the embedding storage (Niko1221#1454), the Pascal
decode fix (Niko1221#1469), q8_1 scale clamps (Niko1221#1448), STRATA_STAGE_PIN opt-in (off:
on by default it corrupted IQ3_S decode after a long prompt), route-resident
and GDN-chunked opt-ins, gfx906 build fix, AMD docs and community benches.

main keeps 33af099 (AMD PCIe link speed/width and GPU name detection) and
a798ac0 (the k8v4 config read-back and 816 B/cell sizing).
Maddoxkkm added a commit to Maddoxkkm/Strata that referenced this pull request Oct 10, 2026
…tch-audit.py + fetched PR diffs)

Line-level audit of the eight patches applied on tuned-1403 against the tuned-141 tree and against
upstream 0.1.41: Niko1221#1323 and Niko1221#1372 are upstream's now, Niko1221#1381/Niko1221#1439/Niko1221#1451 are re-applied on 141, while
Niko1221#1416 (CPU share), Niko1221#1448 (q8_1 finite-ds) and Niko1221#1457 (HC scratch reuse) have no counterpart there.
patch-audit.py compares a diff's added code lines against a tree, which survives the rebases and
reworkings that defeat 'git apply -R --check'.
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