docs(vault): one fact, one owner - de-stale the technique and era pages (C1-C6) #24
@@ -342,7 +342,11 @@ file is a defect: it is the next thing to go stale.
|
|||||||
serve script that consumes it, and in the endpoint page. Every other page
|
serve script that consumes it, and in the endpoint page. Every other page
|
||||||
cites it by link.
|
cites it by link.
|
||||||
- Technique pages (spec decode, KV math, offload budgets, PP bandwidth) stay
|
- Technique pages (spec decode, KV math, offload budgets, PP bandwidth) stay
|
||||||
technique pages; they stop carrying per-endpoint throughput tables.
|
technique pages: they stop carrying a per-endpoint throughput table or a live
|
||||||
|
shape, but a campaign ledger that exists nowhere else is owned by the page that
|
||||||
|
measured it. The defect is two pages carrying one figure, not a number living on a
|
||||||
|
technique page — move a figure only when an endpoint page or an env header is its
|
||||||
|
home; otherwise leave it in place and name the era it measured.
|
||||||
|
|
||||||
## Model Config (harness)
|
## Model Config (harness)
|
||||||
|
|
||||||
@@ -938,6 +942,14 @@ linked runbooks.
|
|||||||
already does all three; ad-hoc fetches tend not to. Gated repos (e.g.
|
already does all three; ad-hoc fetches tend not to. Gated repos (e.g.
|
||||||
`orcarouter/Qwen3.8-Flash-Next-Uncensored-GGUF`, same 104.09 GiB Q4_K_S)
|
`orcarouter/Qwen3.8-Flash-Next-Uncensored-GGUF`, same 104.09 GiB Q4_K_S)
|
||||||
return 403 even with the host's HF token until that account accepts the gate.
|
return 403 even with the host's HF token until that account accepts the gate.
|
||||||
|
- **A scout verdict is a lead, never a finding.** In the 2026-10-19 vault de-dup
|
||||||
|
campaign, four read-only scouts worked the same pages: one classified era pages as
|
||||||
|
stale *because* they document retired payloads (that is an era page's content), one
|
||||||
|
reported files that do not exist, one reported duplications that grep disproved
|
||||||
|
(`457.9 t/s` and the ping-RTT table are solo-held by `Ethernet Bandwidth Math`),
|
||||||
|
and one cited a line number past the end of the file it judged. Re-verify every
|
||||||
|
claimed duplicate and every claimed staleness against the file and today's fleet
|
||||||
|
state before editing; a scout yield buys no evidence.
|
||||||
|
|
||||||
## Runbook Index
|
## Runbook Index
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ timestamp: 2026-09-03
|
|||||||
|
|
||||||
DFlash and DSpark are the two newest speculative decoding methods. They draft many tokens in one parallel pass instead of one token at a time. This reduces decode latency on memory-bound workloads.
|
DFlash and DSpark are the two newest speculative decoding methods. They draft many tokens in one parallel pass instead of one token at a time. This reduces decode latency on memory-bound workloads.
|
||||||
|
|
||||||
DFlash comes from Z Lab at UC Berkeley. DSpark comes from DeepSeek. Both work with vLLM and llama.cpp. Both have draft models for the Qwen3.6 models that Dankserver and Dankclaw run.
|
DFlash comes from Z Lab at UC Berkeley. DSpark comes from DeepSeek. Both work with vLLM and llama.cpp. Both publish draft models for the Qwen3.5/Qwen3.6 families (table below); what any of them pairs with on this fleet is an era on [[frank-dragoon]] or [[frank-zealot]].
|
||||||
|
|
||||||
## How DFlash Works
|
## How DFlash Works
|
||||||
|
|
||||||
@@ -115,12 +115,12 @@ unconditionally, while **context-backed** types (`draft-mtp`, `draft-dflash`,
|
|||||||
- Internal order is fixed (ngram types first, then drafters); CLI order is
|
- Internal order is fixed (ngram types first, then drafters); CLI order is
|
||||||
irrelevant.
|
irrelevant.
|
||||||
- **A legal chain can still lose on a recurrent model.** `draft-mtp,ngram-mod`
|
- **A legal chain can still lose on a recurrent model.** `draft-mtp,ngram-mod`
|
||||||
on the qwen35 hybrid (frank-dragoon era) measured −15 % prose / −7 %
|
on the qwen35 hybrid loses on both traffic shapes (2026-10-03): adding the
|
||||||
block-copy (2026-10-03): adding the ngram layer logs `recurrent state
|
ngram layer logs `recurrent state rollback is not compatible with
|
||||||
rollback is not compatible with 'ngram-mod' - disabling rollback support`,
|
'ngram-mod' - disabling rollback support`, and MTP verification depends on
|
||||||
and MTP verification depends on that rollback, so acceptance drops on ALL
|
that rollback, so acceptance drops on ALL traffic even where the matcher
|
||||||
traffic even where the matcher fires. Measure chains per architecture,
|
fires. The measured size of each loss is [[frank-dragoon]]'s (Laws). Measure
|
||||||
never by analogy.
|
chains per architecture, never by analogy.
|
||||||
- ngram-mod prints NO startup banner — the load log shows only the drafter's
|
- ngram-mod prints NO startup banner — the load log shows only the drafter's
|
||||||
`adding speculative implementation` line. Never conclude "chain not
|
`adding speculative implementation` line. Never conclude "chain not
|
||||||
engaged" from the load log; identify behaviourally (`draft_n` > 0 only
|
engaged" from the load log; identify behaviourally (`draft_n` > 0 only
|
||||||
@@ -198,7 +198,10 @@ Compatible MTP-only draft GGUFs on Hugging Face:
|
|||||||
|
|
||||||
Speculative decoding is lossless under rejection sampling: the target verifies every draft token. A draft head from the base model works with a derivative target; wrong proposals just lower the acceptance rate. The accepted MTP draft lengths are 2-3 tokens; the "MTP Defaults Are a Trap" writeup (thefrontierlab.ai) documents the tuning pitfalls.
|
Speculative decoding is lossless under rejection sampling: the target verifies every draft token. A draft head from the base model works with a derivative target; wrong proposals just lower the acceptance rate. The accepted MTP draft lengths are 2-3 tokens; the "MTP Defaults Are a Trap" writeup (thefrontierlab.ai) documents the tuning pitfalls.
|
||||||
|
|
||||||
On Dankclaw, `draft-dflash` remains the benchmarked winner (20.2 t/s at 4k vs 16.9 for DFlash+ngram and 8.7 for ngram-only). MTP is a viable alternative to test, not a bug fix: the parallel-stream releases investigated on 2026-08-13 were client-side aborts and a Dankserver crash, not speculative decoding behavior (see [[deployment]]).
|
On the mid-August 2026 Dankclaw shape `draft-dflash` was the benchmarked winner
|
||||||
|
at 4k — 20.2 t/s, against 16.9 with ngram layered on and 8.7 ngram-only; those
|
||||||
|
three figures are that retired llama.cpp era's property ([[frank-dragoon]] owns
|
||||||
|
the era and its shape). MTP is a viable alternative to test, not a bug fix: the parallel-stream releases investigated on 2026-08-13 were client-side aborts and a Dankserver crash, not speculative decoding behavior (see [[deployment]]).
|
||||||
|
|
||||||
## Draft Models
|
## Draft Models
|
||||||
|
|
||||||
@@ -213,13 +216,12 @@ DFlash draft model sizes for the models on these servers:
|
|||||||
|
|
||||||
The DFlash draft is not a standalone model. It must pair with its target model. The model cards recommend block size 8 for higher concurrency and 16 for single-stream throughput.
|
The DFlash draft is not a standalone model. It must pair with its target model. The model cards recommend block size 8 for higher concurrency and 16 for single-stream throughput.
|
||||||
|
|
||||||
## Deployment on Dankserver (NVIDIA RTX 3090)
|
## DFlash on an RTX 3090 (Ampere) — the archived vLLM path
|
||||||
|
|
||||||
The Dankserver llama.cpp deployment (`frank-zealot`, Qwen3.6-35B-A3B) is **active** on Dankserver (port 7770) as of the 2026-08-17 redo (the earlier 2026-08-16/17 retirement of this service was reversed when the PP split was retired). The vLLM material below documents the archived AWQ/DFlash path on the same hardware.
|
DFlash was tried on the 3090 line, lost there to the ngram chain, and was never
|
||||||
|
kept deployed; that card's payloads, shapes and rates are [[frank-zealot]]'s
|
||||||
> **DFlash retired from active service.** `DFlash` (draft-dflash) was tested initially but did not deliver the desired speed gains under the `frank-zealot` workload (see ngram-mod benchmarks below). The `Alittlehammmer/Qwen3.6-35B-A3B-DFlash` draft GGUF remains in `/home/dank/models/` as reference material only.
|
(its Eras rows are the llama.cpp arms the draft was tested against). What
|
||||||
|
transfers is the Ampere arithmetic — compute capability 8.6, so:
|
||||||
The vLLM material below documents the archived AWQ/DFlash path on the same hardware. The RTX 3090 is Ampere (compute capability 8.6). Use these conditions:
|
|
||||||
|
|
||||||
- FP8 KV cache is valid on CUDA 12.
|
- FP8 KV cache is valid on CUDA 12.
|
||||||
- FP8 weights compute through a fallback path; no native FP8 tensor cores.
|
- FP8 weights compute through a fallback path; no native FP8 tensor cores.
|
||||||
@@ -248,11 +250,15 @@ docker run --rm --name vllm-qwen36-dflash \
|
|||||||
--gpu-memory-utilization 0.95
|
--gpu-memory-utilization 0.95
|
||||||
```
|
```
|
||||||
|
|
||||||
## Deployment on Dankclaw (AMD Strix Halo gfx1151)
|
## DFlash and DSpark on Strix Halo (gfx1151) — what killed them
|
||||||
|
|
||||||
`frank-dragoon` on Dankclaw ran the llama.cpp pipeline-parallel head (Qwen3.8-27B-Uncensored Q6_K) on port 7770, RPC-split with the Dankserver worker. Spec was the standalone MTP draft over the ngram-mod fallback, 1 slot at 262144 ctx, q8_0/f16 KV, head GPU side ROCm0. This page is a historical record of that era (mid-August 2026); for the current deployment see [[frank-dragoon]].
|
Both context-backed drafters died the same way on the iGPU: under parallel load.
|
||||||
|
DSpark took `ROCm error: an illegal memory access` inside the shared draft
|
||||||
History: before `--spec-default`, the box ran DSpark (`draft-dspark`, retired 2026-08-15 after a ROCm illegal-memory-access crash under two concurrent 16k prompts) and before that bundled MTP (`draft-mtp`, retired same day). DFlash was retired on 2026-08-14 (premature-EOS under parallel load). The old DFlash draft GGUF (`Qwen3.6-27B-DFlash-Q8_0.gguf`), the MTP-only drafter (`Qwen3.6-27B-MTP-ONLY-Q8_0.gguf`), and the DSpark draft (`Qwen3.8-27B-DSpark-Q8_0.gguf`) remain in `/home/dank/models/` as reference only.
|
context with two concurrent 16k prompts; DFlash corrupted multi-slot into
|
||||||
|
premature EOS and was retired first. The timeline, the crash class, the
|
||||||
|
"concurrency is the trigger, not size" finding and the `PARALLEL=1` workaround
|
||||||
|
are on [[qwen3.8-spec-matrix]]; the shape they were measured on is
|
||||||
|
[[frank-dragoon]]'s mid-August 2026 era.
|
||||||
|
|
||||||
## A/B protocol on a live llama.cpp endpoint
|
## A/B protocol on a live llama.cpp endpoint
|
||||||
|
|
||||||
@@ -359,16 +365,18 @@ pay for K sequential forwards.
|
|||||||
Trained heads are target-specific: EAGLE/DFlash consume the TARGET's hidden
|
Trained heads are target-specific: EAGLE/DFlash consume the TARGET's hidden
|
||||||
states, so a dense-27B DFlash2 is useless for a 512-expert MoE trunk.
|
states, so a dense-27B DFlash2 is useless for a 512-expert MoE trunk.
|
||||||
|
|
||||||
**Step 4 — acceptance reality checks.** Fleet datum: a trained z-lab DFlash2
|
**Step 4 — acceptance reality checks.** Treat 40–60 % as the honest band for a
|
||||||
at depth 7 accepted ~41 % on its matched target (`draft-dflash 7 → 43.5
|
matched pair; the arm that anchors the bottom of it on this fleet is the
|
||||||
tok/s`); treat 40–60 % as the honest band for a matched pair. Cheapest proxy
|
depth-7 `draft-dflash` row of [[frank-medium-llamacpp-dflash2]]'s spec table
|
||||||
for `p` at temp 0 when both models are greedy and share a tokenizer: greedy
|
(accepted share, rate and VRAM for every depth are in that table). Cheapest
|
||||||
continuation agreement on identical prompts, two API calls, no weights moved.
|
proxy for `p` at temp 0 when both models are greedy and share a tokenizer:
|
||||||
llama.cpp can also synthesize the projection without any draft artifact:
|
greedy continuation agreement on identical prompts, two API calls, no weights
|
||||||
|
moved. llama.cpp can also synthesize the projection without any draft artifact:
|
||||||
`--spec-synth-rates P0,P1,...` / `--spec-synth-len L`. Speculation pays IN
|
`--spec-synth-rates P0,P1,...` / `--spec-synth-len L`. Speculation pays IN
|
||||||
PROPORTION TO HOW SLOW THE TARGET IS — the same 41 % gave 2.3x on an
|
PROPORTION TO HOW SLOW THE TARGET IS — that band's midpoint was worth 2.3× on
|
||||||
18.8 tok/s layer-split target and a loss on a 25 tok/s one; fast targets are
|
the slow two-card layer-split target and a LOSS on the 25 tok/s target of the
|
||||||
usually sparse MoE, the worst case for drafting.
|
worked example above; fast targets are usually sparse MoE, the worst case for
|
||||||
|
drafting.
|
||||||
|
|
||||||
**Step 5 — check the attachment surface BEFORE the arithmetic.** Closed
|
**Step 5 — check the attachment surface BEFORE the arithmetic.** Closed
|
||||||
engines refuse external drafters by design: halogen-flash-server's
|
engines refuse external drafters by design: halogen-flash-server's
|
||||||
@@ -403,7 +411,7 @@ measurement that would settle it.
|
|||||||
|
|
||||||
- Speculative decoding helps low-QPS, memory-bound, latency-focused workloads. It helps less at high QPS.
|
- Speculative decoding helps low-QPS, memory-bound, latency-focused workloads. It helps less at high QPS.
|
||||||
- DFlash needs a non-causal attention backend; the ROCm flash_attn backend must be validated before production use.
|
- DFlash needs a non-causal attention backend; the ROCm flash_attn backend must be validated before production use.
|
||||||
- The old `--swap-space` flag no longer exists in current vLLM. Use `--kv-offloading-size`.
|
- The old `--swap-space` flag is retired; the live CPU-KV-offload knob pair is owned by [[RAM CPU Offloading in VLLM]].
|
||||||
- `--speculative-config` is the preferred CLI. Legacy `--spec-method`, `--spec-model`, and `--spec-tokens` flags still exist.
|
- `--speculative-config` is the preferred CLI. Legacy `--spec-method`, `--spec-model`, and `--spec-tokens` flags still exist.
|
||||||
- Use `rejection_sample_method` default `strict` for lossless output.
|
- Use `rejection_sample_method` default `strict` for lossless output.
|
||||||
|
|
||||||
|
|||||||
@@ -17,66 +17,59 @@ Dates: researched 2026-08. Hardware is verified on the live machine unless
|
|||||||
marked "verify first". Re-verified 2026-08-15/16; corrections marked below.
|
marked "verify first". Re-verified 2026-08-15/16; corrections marked below.
|
||||||
|
|
||||||
**Live today (2026-10-18).** The era described below — llama.cpp on the 8060S
|
**Live today (2026-10-18).** The era described below — llama.cpp on the 8060S
|
||||||
iGPU behind :7770 — is retired. Dankclaw now serves
|
iGPU — is retired; what runs on this box now (both endpoints, their engines and
|
||||||
[[frank-dragoon]] (halogen-flash-server 0.16.2, port
|
ports) is [[frank-dragoon]]'s and [[frank-zealot]]'s pages, and both run under their
|
||||||
7770) and [[frank-zealot]] (llama.cpp PrismML fork on
|
repo units today — no drift open as of 2026-10-19 (`frank-zealot` active since
|
||||||
the RTX 3090, port 7771 — drift today: that unit is `failed` since 2026-10-18
|
2026-10-18 21:06, the deployer's 2-slot reslice; `frank-dragoon` active). The OS facts
|
||||||
03:40 and a hand-run 9B-MTP process answers the port), and boots `iommu=pt` since 2026-10-18
|
are this page's: `iommu=pt` since 2026-10-18 ([[dankclaw-iommu-translation-off]]), and
|
||||||
([[dankclaw-iommu-translation-off]]). The numbers below are the measurements of
|
the `ttm` ceiling and NVMe scheduler rows below were re-checked 2026-10-18 and
|
||||||
the era they were taken in; the `ttm` ceiling and the NVMe scheduler rows were
|
still hold. Every benchmark number below is a measurement of the era it was
|
||||||
re-checked 2026-10-18 and still hold.
|
taken in.
|
||||||
|
|
||||||
## Corrections (re-verified 2026-08-15/16)
|
## Corrections (re-verified 2026-08-15/16)
|
||||||
|
|
||||||
- **Backend**: that era's production was **Vulkan0**, not ROCm. Measured on this box
|
- **Backend**: that era's production was **Vulkan0**, not ROCm. On this box ROCm
|
||||||
(b10433): Vulkan 25.13 t/s vs ROCm 24.33 t/s decode at 16k; at 262k ctx
|
wins prefill and Vulkan wins decode, and the decode gap widens with context:
|
||||||
Vulkan decodes 48% faster (5.68 vs 3.83 t/s). ROCm wins prefill (410 vs
|
the 64k A/B is [[qwen3.8-strix-optimizations]] §4, the 262k A/B is
|
||||||
302 t/s @64k). The "HIP out-performs Vulkan for decode" claim did not
|
[[qwen3.8-spec-matrix]] §High-Context Backend Comparison. The "HIP
|
||||||
hold on the 8060S. See [[frank-dragoon]].
|
out-performs Vulkan for decode" claim did not hold on the 8060S.
|
||||||
- **Power profile**: the `/sys/class/drm/card0/device/power_profile` file
|
- **Power profile**: the `/sys/class/drm/card0/device/power_profile` file
|
||||||
does not exist on this machine (checked 2026-08-15). GPU DPM is already
|
does not exist on this machine (checked 2026-08-15). GPU DPM is already
|
||||||
`performance`, forced level `auto`. This item is N/A.
|
`performance`, forced level `auto`. This item is N/A.
|
||||||
- **KV cache**: production ran `q8_0` K **and** `q8_0` V (both quantized). The law
|
- **KV cache**: production ran `q8_0` K **and** `q8_0` V (both quantized). What
|
||||||
still holds on `frank-zealot` (`CACHE_TYPE_K=q8_0`, `CACHE_TYPE_V=q8_0` —
|
`frank-zealot` runs now is its own Current shape — this row is not it.
|
||||||
`scripts/frank-zealot.env:55-56`).
|
|
||||||
- **Spec**: DFlash/DSpark are retired. That era's production was `--spec-default`
|
- **Spec**: DFlash/DSpark are retired. That era's production was `--spec-default`
|
||||||
(ngram-mod) with draft-mtp first. See [[qwen3.8-spec-matrix]]. Today `frank-zealot`
|
(ngram-mod) with draft-mtp first — timeline on [[qwen3.8-spec-matrix]]; the
|
||||||
is configured with speculation **off** (`SPEC_TYPE=none` — `scripts/frank-zealot.env:67`).
|
spec setting each endpoint runs today is on its own page.
|
||||||
- **TTM**: raised to 114 GiB on 2026-08-25, set live (no reboot) and
|
- **TTM**: the `pages_limit` raise that removed the ~15 GiB ceiling is recorded
|
||||||
persisted in `/etc/modprobe.d/ttm.conf`. The effective VRAM ceiling that
|
once on [[Dankclaw System Specs]] (Memory).
|
||||||
once held the service at ~15 GiB is gone.
|
|
||||||
|
|
||||||
## Verified Memory Picture (measured 2026-08-11)
|
## Verified Memory Picture (measured 2026-08-11)
|
||||||
|
|
||||||
| Figure | Value | Source |
|
| Figure | Value | Source |
|
||||||
| ------ | ----- | ------ |
|
| ------ | ----- | ------ |
|
||||||
| OS physical RAM | 30.5 GiB | `/proc/meminfo` |
|
| OS physical RAM | 30.5 GiB | `/proc/meminfo` |
|
||||||
| TTM pages_limit | 114 GiB (29,883,536 x 4KiB) — raised 2026-08-25 | `/sys/module/ttm/parameters/pages_limit` |
|
|
||||||
| ROCm VRAM total | 96.0 GiB | `rocm-smi --showmeminfo vram` under the then firmware VGM carve |
|
| ROCm VRAM total | 96.0 GiB | `rocm-smi --showmeminfo vram` under the then firmware VGM carve |
|
||||||
| ROCm VRAM used | 76.2 GiB | `rocm-smi` while serving 3x200700 |
|
| ROCm VRAM used | 76.2 GiB | `rocm-smi` while serving 3x200700 |
|
||||||
|
|
||||||
That 2026-08 reading is the firmware-VGM era: the BIOS carved ~96 GiB as
|
That 2026-08 reading is the firmware-VGM era: the BIOS carved ~96 GiB as
|
||||||
"dedicated" iGPU VRAM, so the kernel saw only ~30 GiB (the same split is
|
"dedicated" iGPU VRAM, so the kernel saw only ~30 GiB (the same split is
|
||||||
recorded in [[ling-3.0-flash-trial]] §Why Vulkan + GTT). The OS now accounts
|
recorded in [[ling-3.0-flash-trial]] §Why Vulkan + GTT; the 76.2 GiB row is an
|
||||||
**121 GiB** (`MemTotal 127108080 kB`, 2026-10-18) and `rocm-smi
|
era [[frank-dragoon]] load reading). Every live number on this box — `MemTotal`,
|
||||||
--showmeminfo vram` reports **2.0 GiB** (2,147,483,648 B) of dedicated VRAM —
|
the ~114 GiB GTT aperture that is the real GPU budget, the 2.0 GiB dedicated
|
||||||
the carve is gone and the GPU budget is the GTT aperture, not the SMI figure
|
carve and the `ttm` page cap — belongs to [[Dankclaw System Specs]], re-read
|
||||||
([[Dankclaw System Specs]]).
|
2026-10-18.
|
||||||
The TTM row above is still live: `pages_limit = 29883536` (114 GiB) and
|
|
||||||
`/etc/modprobe.d/ttm.conf` still carries the `options ttm` line (both read
|
|
||||||
2026-10-18).
|
|
||||||
|
|
||||||
This split is the Strix Halo GTT/VGM design. It drives the batch/ubatch memory
|
This split is the Strix Halo GTT/VGM design. It drives the batch/ubatch memory
|
||||||
limits documented in [[frank-dragoon]].
|
limits documented in [[frank-dragoon]].
|
||||||
|
|
||||||
## 1. Self-Hosted Agentic Tools
|
## 1. Self-Hosted Agentic Tools
|
||||||
|
|
||||||
All of these connect to the local OpenAI-compatible endpoint
|
All of these connect to the local OpenAI-compatible endpoint on
|
||||||
(`http://127.0.0.1:7770/v1`). Today that port is **halogen-flash-server**, not a
|
`:7770` (which engine owns that port is [[frank-dragoon]]'s to say), and the
|
||||||
llama.cpp server, and the address must be the IPv4 literal: `curl
|
address must be the IPv4 literal: `curl http://localhost:7770/v1/models` returns
|
||||||
http://localhost:7770/v1/models` returns nothing while
|
nothing while `http://127.0.0.1:7770/v1/models` answers 200 (checked 2026-10-18
|
||||||
`http://127.0.0.1:7770/v1/models` answers 200 (checked 2026-10-18 — the rootless
|
— the rootless podman publish is IPv4-only). None need NVIDIA.
|
||||||
podman publish is IPv4-only). None need NVIDIA.
|
|
||||||
|
|
||||||
| Tool | Use | Endpoint config | Priority |
|
| Tool | Use | Endpoint config | Priority |
|
||||||
| ---- | --- | --------------- | -------- |
|
| ---- | --- | --------------- | -------- |
|
||||||
@@ -90,12 +83,13 @@ podman publish is IPv4-only). None need NVIDIA.
|
|||||||
| Qdrant | Vector store for RAG | Standalone, CPU-native | Low |
|
| Qdrant | Vector store for RAG | Standalone, CPU-native | Low |
|
||||||
|
|
||||||
The pragmatic first installs are Open WebUI, Cline, and Aider. They all work
|
The pragmatic first installs are Open WebUI, Cline, and Aider. They all work
|
||||||
with the endpoint on 7770 and need no extra GPU. The 7770 endpoint today is
|
with the endpoint on 7770 and need no extra GPU.
|
||||||
halogen-flash-server, not llama.cpp.
|
|
||||||
|
|
||||||
## 2. Inference Runtime Tuning (llama.cpp on gfx1151)
|
## 2. Inference Runtime Tuning (llama.cpp on gfx1151)
|
||||||
|
|
||||||
Verified against the running service and llama.cpp source.
|
Verified against that era's running service and llama.cpp source; the era is
|
||||||
|
retired ([[frank-dragoon]]), so this table is history and a method, not a live
|
||||||
|
TODO list.
|
||||||
|
|
||||||
| Change | Recommendation | Priority |
|
| Change | Recommendation | Priority |
|
||||||
| ------ | -------------- | -------- |
|
| ------ | -------------- | -------- |
|
||||||
@@ -104,8 +98,8 @@ Verified against the running service and llama.cpp source.
|
|||||||
| Flash attention | Leave `--flash-attn auto`. It helps prompt processing, not decode. | Keep |
|
| Flash attention | Leave `--flash-attn auto`. It helps prompt processing, not decode. | Keep |
|
||||||
| Load mode | Start with mmap (default). Enable `--mlock` only if page-fault stutter appears. | Optional |
|
| Load mode | Start with mmap (default). Enable `--mlock` only if page-fault stutter appears. | Optional |
|
||||||
| Threads | Use `--threads 12 --threads-batch 16 --threads-http 1` for 16 Zen5 cores + 3 slots. Frees cores for the ROCm driver. | Medium |
|
| Threads | Use `--threads 12 --threads-batch 16 --threads-http 1` for 16 Zen5 cores + 3 slots. Frees cores for the ROCm driver. | Medium |
|
||||||
| DFlash n_max | Current 8 (block 16) is high. Try `--spec-draft-n-max 5`; it may reduce rejection cost at the same throughput. | Verify |
|
| DFlash n_max | Depth 8 (block 16) was high; a shallower draft cuts rejection cost at the same throughput. Sweep depth per the A/B protocol in [[DFlash DSpark Speculative Decoding]]. | Verify |
|
||||||
| ngram layering | Measured slower than DFlash alone at 4k (16.9 vs 20.2 t/s). Not enabled. | Keep off |
|
| ngram layering | Layering ngram on the DFlash draft measured slower than the draft alone at 4k — figures on [[DFlash DSpark Speculative Decoding]]. | Keep off |
|
||||||
|
|
||||||
## 3. Server / OS / Hardware Settings
|
## 3. Server / OS / Hardware Settings
|
||||||
|
|
||||||
@@ -113,7 +107,7 @@ All require root and a reboot for the modprobe change.
|
|||||||
|
|
||||||
| Setting | Action | Effect | Priority |
|
| Setting | Action | Effect | Priority |
|
||||||
| ------- | ------ | ------ | -------- |
|
| ------- | ------ | ------ | -------- |
|
||||||
| TTM GPU pool | `/etc/modprobe.d/ttm.conf` → `options ttm pages_limit=29883536 page_pool_size=29883536` (applied 2026-08-25, set live then persisted) | Lifts the 15 GiB cap to 114 GiB; the full 262k KV + Q8 AGENT payload fit in one slot | Done |
|
| TTM GPU pool | Raised 2026-08-25; the knob, its value and its persistence file are [[Dankclaw System Specs]]'s (Memory row) | Lifted the ~15 GiB kernel-page ceiling so a full 262k KV plus a ~30 GB payload fits one slot | Done |
|
||||||
| Power profile | **N/A on this machine** (2026-08-15; re-checked 2026-10-18: no `power_profile` under `/sys/class/drm/card0/device/` or `card1/device/`); GPU DPM already `performance` | none | ~~Medium~~ |
|
| Power profile | **N/A on this machine** (2026-08-15; re-checked 2026-10-18: no `power_profile` under `/sys/class/drm/card0/device/` or `card1/device/`); GPU DPM already `performance` | none | ~~Medium~~ |
|
||||||
| NVMe scheduler | Already `none` (`[none] mq-deadline` in `/sys/block/nvme0n1/queue/scheduler`, re-read 2026-10-18) | No change | Done |
|
| NVMe scheduler | Already `none` (`[none] mq-deadline` in `/sys/block/nvme0n1/queue/scheduler`, re-read 2026-10-18) | No change | Done |
|
||||||
| BIOS VGM | Set Variable Graphics Memory / UMA to "High" in the EVO-X2 BIOS | Max dedicated VRAM for the GPU carve-out; verify in the live BIOS | Verify |
|
| BIOS VGM | Set Variable Graphics Memory / UMA to "High" in the EVO-X2 BIOS | Max dedicated VRAM for the GPU carve-out; verify in the live BIOS | Verify |
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ The NPU endpoint is retired (2026-09-11; [[frank-npu]]). The `frank-zealot` name
|
|||||||
| System RAM | 121 GiB (shared CPU + GPU; `free -g` total 121, `MemTotal 127108080 kB`, 2026-10-18) |
|
| System RAM | 121 GiB (shared CPU + GPU; `free -g` total 121, `MemTotal 127108080 kB`, 2026-10-18) |
|
||||||
| GPU-Visible (ROCm) | ~114 GiB GTT aperture (`mem_info_gtt_total` 122,402,963,456 B — the budget) |
|
| GPU-Visible (ROCm) | ~114 GiB GTT aperture (`mem_info_gtt_total` 122,402,963,456 B — the budget) |
|
||||||
| Swap | 64 GB `/swap.img` (`swapon`, 2026-10-18; `free` reports 63 GiB) |
|
| Swap | 64 GB `/swap.img` (`swapon`, 2026-10-18; `free` reports 63 GiB) |
|
||||||
|
| TTM page cap | `ttm.pages_limit = 29883536` (114 GiB of 4 KiB pages) and `page_pool_size=29883536`, persisted in `/etc/modprobe.d/ttm.conf`, applied live 2026-08-25 and re-read 2026-10-18 (`/sys/module/ttm/parameters/pages_limit`). The kernel default is half of RAM, so in the firmware-VGM era (~30 GiB visible) the cap was ~15 GiB and a 28 GB payload plus a 262k KV cache could not load — this is the row every other page should cite |
|
||||||
| /dev/shm | 61 GiB tmpfs (half of RAM, `df /dev/shm`, 2026-10-18) |
|
| /dev/shm | 61 GiB tmpfs (half of RAM, `df /dev/shm`, 2026-10-18) |
|
||||||
|
|
||||||
### Storage
|
### Storage
|
||||||
|
|||||||
@@ -147,10 +147,10 @@ LAN/SATA/WiFi:
|
|||||||
they were in separate IOMMU groups (15 and 20 — re-read 2026-10-18: still 15
|
they were in separate IOMMU groups (15 and 20 — re-read 2026-10-18: still 15
|
||||||
and 20), and both root ports had ACS `ReqRedir+`, so this page inferred P2P
|
and 20), and both root ports had ACS `ReqRedir+`, so this page inferred P2P
|
||||||
would hairpin at the root complex. **That inference is superseded:** the live
|
would hairpin at the root complex. **That inference is superseded:** the live
|
||||||
engine says the opposite about the same pair — "I device: the 2 cards reach
|
engine reports the two cards reaching each other's memory directly, which
|
||||||
each other's memory directly (peer to peer)" (`podman logs frank-archon`,
|
[[frank-archon]] and [[Dankserver System Specs]] record. Plain P2P traffic
|
||||||
2026-10-15 boot). Plain P2P traffic measured 45.27 GB/s bidirectional on the
|
measured 45.27 GB/s bidirectional on the *old* board — DMA was never the gate,
|
||||||
*old* board — DMA was never the gate, atomics were.
|
atomics were.
|
||||||
- Kernel 7.0.0-31-generic with `iommu=pt` then; this host runs 7.0.0-38-generic
|
- Kernel 7.0.0-31-generic with `iommu=pt` then; this host runs 7.0.0-38-generic
|
||||||
with `iommu=pt` today (`/proc/cmdline`, read 2026-10-18). Both were ruled out
|
with `iommu=pt` today (`/proc/cmdline`, read 2026-10-18). Both were ruled out
|
||||||
as causes ([above](#ruled-out-empirically-do-not-re-derive)) and this host's
|
as causes ([above](#ruled-out-empirically-do-not-re-derive)) and this host's
|
||||||
@@ -163,10 +163,9 @@ launched since the swap. Until the 2-rank probe runs — or a `--split-mode row`
|
|||||||
boot that does *not* log `internal AllReduce init failed ... falling back to
|
boot that does *not* log `internal AllReduce init failed ... falling back to
|
||||||
meta-backend butterfly` — "collectives work here" was a strong expectation, not a
|
meta-backend butterfly` — "collectives work here" was a strong expectation, not a
|
||||||
measurement. **RCCL never got that measurement**; what settled the operational
|
measurement. **RCCL never got that measurement**; what settled the operational
|
||||||
question instead is production traffic: radiance's TP=2 wire moves cross-rank
|
question instead is production traffic — radiance's TP=2 wire carries cross-rank
|
||||||
all-reduces over the direct P2P path and reports its own precision — "tp wire:
|
all-reduces over the direct P2P path and prints its own precision, and the
|
||||||
LOSSY (--tp-wire wht6) at 128 KiB a message and above … Steps of at most 25 rows
|
measured `wht6` banner with its exact-step bound is on [[frank-archon]].
|
||||||
are exact" (`podman logs frank-archon`, 2026-10-15 boot).
|
|
||||||
|
|
||||||
## Measured matrix
|
## Measured matrix
|
||||||
|
|
||||||
@@ -233,35 +232,34 @@ landed, at x8/x8, clears the arithmetic with room to spare.
|
|||||||
|
|
||||||
Both cooperation modes were run on this host on 2026-09-20 — the same salted
|
Both cooperation modes were run on this host on 2026-09-20 — the same salted
|
||||||
10-prompt battery (`scripts/bench-conversation.py`), the service stopped and
|
10-prompt battery (`scripts/bench-conversation.py`), the service stopped and
|
||||||
masked between arms. Decode/prefill are geometric means over the ten rows;
|
masked between arms. The arm table is [[frank-medium-radiance-mxfp4]]'s bench of
|
||||||
burst-4 is four concurrent copies of one prompt, reported as aggregate tokens/s.
|
record (arms R = radiance TP=2 + DFlash2 as deployed, I = the llama.cpp layer
|
||||||
|
split that preceded it, L = llama.cpp `--split-mode tensor` against RCCL); this
|
||||||
|
page keeps only the verdict. **TP=2 won on every axis — roughly 2.1× decode and
|
||||||
|
3.6× at 4-way concurrency over the layer split — and replaced the layer split the
|
||||||
|
day of measurement.**
|
||||||
|
|
||||||
| Shape | Cross-device path | Decode | TTFT | Prefill | burst-4 |
|
Arm L carries a caveat no flag can remove: llama.cpp's tensor mode could not load
|
||||||
|---|---|---|---|---|---|
|
the DFlash2 drafter (it aborts at `ggml-backend.cpp:941` — a draft weight
|
||||||
| **radiance TP=2 + DFlash2 — deployed** | R4D one-shot allreduce | **95.8 t/s** | **0.21 s** | **1493.6 t/s** | **259.4 t/s (65.6/stream)** |
|
|
||||||
| llama.cpp layer split 32:33 + DFlash2 — predecessor | none, boundary activation copy | 45.7 t/s | 0.72 s | ~530 t/s | 71.7 t/s |
|
|
||||||
| llama.cpp `--split-mode tensor` 1:1 | RCCL allreduce | 30.5 t/s | 0.71 s | n/r | 54.3 t/s |
|
|
||||||
|
|
||||||
Row 3 carries a caveat that no flag can remove: llama.cpp's tensor mode could not
|
|
||||||
load the DFlash2 drafter (it aborts at `ggml-backend.cpp:941` — a draft weight
|
|
||||||
pre-allocated on the non-primary device has no backend once `n_copies == 1`), so
|
pre-allocated on the non-primary device has no backend once `n_copies == 1`), so
|
||||||
it decoded **without** speculation while the other two rows decoded with it. The
|
it decoded **without** speculation while the other arms decoded with it; and part
|
||||||
comparison that decides anything is row 1 against row 2, and some of that gap is
|
of R's margin over I is the 4-bit MXFP4 checkpoint, not the parallelism.
|
||||||
the 4-bit MXFP4 checkpoint rather than the parallelism.
|
|
||||||
|
|
||||||
Two numbers elsewhere on this page are therefore not interchangeable:
|
Two numbers elsewhere on this page are therefore not interchangeable:
|
||||||
|
|
||||||
- The 272 t/s recorded 2026-09-16 is **prefill**, on a **butterfly** allreduce,
|
- The 272 t/s recorded 2026-09-16 is **prefill**, on a **butterfly** allreduce,
|
||||||
with RCCL off, on the old board. It was never a TP decode number.
|
with RCCL off, on the old board. It was never a TP decode number, and its
|
||||||
- 26.3 t/s from the same table is that butterfly tensor's decode. Row 3's 30.5 is
|
paired decode figure is in "The third path" below.
|
||||||
an RCCL tensor decode a day later: same shape family, different collective path.
|
- The butterfly tensor arm and the RCCL tensor arm a day later are the same shape
|
||||||
|
family on different collective paths; the measured pair lives with
|
||||||
|
[[frank-medium-radiance-mxfp4]]'s arms.
|
||||||
|
|
||||||
RCCL needs PCIe atomics on *every* participating GPU — the gate the old board
|
RCCL needs PCIe atomics on *every* participating GPU — the gate the old board
|
||||||
failed. vLLM's R4D one-shot allreduce dispatches no collective at all, which is
|
failed. vLLM's R4D one-shot allreduce dispatches no collective at all, which is
|
||||||
why TP=2 runs today rather than merely "being unblocked": the image ships TheRock
|
why TP=2 runs today rather than merely "being unblocked": the image ships TheRock
|
||||||
RCCL, and TheRock carries no gfx1201 device code (`invalid device function`), so
|
RCCL, and TheRock carries no gfx1201 device code (`invalid device function`), so
|
||||||
radiance could not have used RCCL on this host even with atomics routed. Ubuntu's
|
radiance could not have used RCCL on this host even with atomics routed. Ubuntu's
|
||||||
RCCL 2.27 does carry gfx1201 kernels, and that is what row 3 linked against.
|
RCCL 2.27 does carry gfx1201 kernels, and that is what arm L linked against.
|
||||||
|
|
||||||
**Rule for any future multi-GPU collective experiment: stop and mask the
|
**Rule for any future multi-GPU collective experiment: stop and mask the
|
||||||
production service first**, per the benchmarking policy, or run it on a host that
|
production service first**, per the benchmarking policy, or run it on a host that
|
||||||
@@ -292,12 +290,11 @@ on the second card, so the atomics gate never comes up.
|
|||||||
|
|
||||||
That is what `frank-medium` ran from 2026-09-16 to 09-20
|
That is what `frank-medium` ran from 2026-09-16 to 09-20
|
||||||
([[frank-medium-llamacpp-dflash2]]): one process, one model, both cards,
|
([[frank-medium-llamacpp-dflash2]]): one process, one model, both cards,
|
||||||
262144 context. Measured against tensor split
|
262144 context. Its measured layer-split rates are that page's; this host's
|
||||||
on this host: 1991 t/s prefill / 18.8 tok/s decode layer-split, against 272 /
|
tensor arm under the butterfly fallback measured 272 t/s prefill / 26.3 tok/s
|
||||||
26.3 tensor (butterfly fallback, no RCCL). **That tensor number is not a
|
decode. **That tensor number is not a prediction for an RCCL-backed build** — it
|
||||||
prediction for an RCCL-backed build** — it is what tensor split costs when the
|
is what tensor split costs when the allreduce degrades to a meta-backend
|
||||||
allreduce degrades to a meta-backend butterfly, and it is the number the
|
butterfly, and it is the number the board-swap path exists to retire.
|
||||||
board-swap path exists to retire.
|
|
||||||
|
|
||||||
The ranking therefore changed twice. On 2026-09-16: software already gets both
|
The ranking therefore changed twice. On 2026-09-16: software already gets both
|
||||||
cards onto one model, so the hardware fix stopped being a capability question
|
cards onto one model, so the hardware fix stopped being a capability question
|
||||||
|
|||||||
@@ -57,7 +57,10 @@ Key properties, per the project README and docs:
|
|||||||
|
|
||||||
## NPU Hardware on Dankclaw
|
## NPU Hardware on Dankclaw
|
||||||
|
|
||||||
Dankclaw runs an AMD Ryzen AI MAX+ 395 (Strix Halo). The chip integrates an XDNA2 NPU rated at 50 TOPS (vendor spec: "NPU TOPS — Up to 50 TOPS", [amd.com product page](https://www.amd.com/en/products/processors/laptop/ryzen/ai-300-series/amd-ryzen-ai-max-plus-395.html)). It sits beside the Radeon 8060S iGPU and shares the same unified memory pool — 30 GiB exposed to the OS in the 2026-08 reading below; the box presents **121 GiB** today (`free -g` total 121, read 2026-10-18).
|
Dankclaw runs an AMD Ryzen AI MAX+ 395 (Strix Halo). The chip integrates an XDNA2 NPU
|
||||||
|
with 50 TOPS of compute and, crucially, **no dedicated VRAM** - it shares system memory
|
||||||
|
via the IOMMU SVA mapping. The budget this page reasons about - 29 GiB usable at
|
||||||
|
4800 MT/s LPDDR5X - is the 2026-08 host state; the live figure is [[Dankclaw System Specs]].
|
||||||
|
|
||||||
Live verification on Dankclaw, 2026-08-16:
|
Live verification on Dankclaw, 2026-08-16:
|
||||||
|
|
||||||
@@ -89,10 +92,9 @@ Budget math for this fleet:
|
|||||||
| Dankserver (Ryzen 7 7700X) | 62 GB | no NPU |
|
| Dankserver (Ryzen 7 7700X) | 62 GB | no NPU |
|
||||||
| FLM bench box (Kraken Point) | 32 or 96 GB | ~16 or ~48 GB |
|
| FLM bench box (Kraken Point) | 32 or 96 GB | ~16 or ~48 GB |
|
||||||
|
|
||||||
2026-10-18 re-read: Dankclaw's OS now reports **121 GiB** (`free -g`) and
|
The half-of-RAM gate scales with host RAM - live figures in [[Dankclaw System Specs]]
|
||||||
Dankserver **246 GiB** (`free -g`), so the half-of-RAM rule would price the NPU
|
and [[Dankserver System Specs]]. The live gate on Dankclaw is still `flm validate`
|
||||||
budget at ~60 GiB and the 7700X box still has no NPU. The 30 GiB / 62 GB rows
|
(it owns the current number).
|
||||||
are the 2026-08-16 state; the table is moot while no NPU endpoint is deployed.
|
|
||||||
|
|
||||||
Weight sizes (approximate, Q4-class):
|
Weight sizes (approximate, Q4-class):
|
||||||
|
|
||||||
@@ -159,7 +161,10 @@ Qwen3.6-35B-A3B (Q4_KS), FLM v0.9.45, Kraken Point **96 GB DRAM**:
|
|||||||
| Decode t/s | 13.65 | 13.41 | 13.09 | 12.51 | 11.24 | 9.51 |
|
| Decode t/s | 13.65 | 13.41 | 13.09 | 12.51 | 11.24 | 9.51 |
|
||||||
| Prefill t/s | 78.98 | 118.04 | 156.43 | 197.93 | 218.84 | 221.96 |
|
| Prefill t/s | 78.98 | 118.04 | 156.43 | 197.93 | 218.84 | 221.96 |
|
||||||
|
|
||||||
Context: the current PP split (head + 3090 worker) decodes at 14-18 t/s for the 27B dense model. A 35B-A3B at ~10-14 t/s on an NPU with 48 GB of RAM budget is not a speed win over the existing topology.
|
- PP and NPU together cost 2.2 GiB + NPU model + ~2 GiB of headroom. The then-current
|
||||||
|
PP split (head + 3090 worker, 2026-08 era - see [[frank-redo-2026-08-17]]) decoded at
|
||||||
|
14-18 t/s for the 27B dense model, so an NPU offload would free the head or upgrade
|
||||||
|
the worker's model.
|
||||||
|
|
||||||
The vendor also claims "over 10x more power-efficient" versus GPU. That is a marketing claim. We have not measured it.
|
The vendor also claims "over 10x more power-efficient" versus GPU. That is a marketing claim. We have not measured it.
|
||||||
|
|
||||||
@@ -219,7 +224,12 @@ Notes:
|
|||||||
|
|
||||||
## Promotion (2026-08-16)
|
## Promotion (2026-08-16)
|
||||||
|
|
||||||
`frank-zealot` now runs the NPU endpoint on Dankclaw (was the Dankserver llama.cpp service). Unit: `scripts/frank-zealot.service` (symlinked into `/etc/systemd/system`), wrapper `scripts/serve-flm-small.sh`, tunables `scripts/frank-zealot.env`. `LimitMEMLOCK=infinity` is set in the unit. Default model: `gemma4-it:e4b`. Swap `FLM_MODEL` in the env to switch.
|
`frank-zealot` then ran the NPU endpoint on Dankclaw (2026-08; the name was reused
|
||||||
|
twice after this window - see the banner - and the NPU unit today is `frank-npu`,
|
||||||
|
masked). Unit: `scripts/frank-zealot.service` (symlinked into `/etc/systemd/system`),
|
||||||
|
wrapper `scripts/serve-flm-small.sh`, tunables `scripts/frank-zealot.env`.
|
||||||
|
`LimitMEMLOCK=infinity` is set in the unit. Default model: `gemma4-it:e4b`. Swap
|
||||||
|
`FLM_MODEL` in the env to switch.
|
||||||
|
|
||||||
### Boot policy (2026-08-17)
|
### Boot policy (2026-08-17)
|
||||||
|
|
||||||
@@ -256,11 +266,13 @@ The 4-stream wall times form a near-perfect 10.7 s ladder. Each stream self-repo
|
|||||||
Consequence: the NPU endpoint is a single lane. It suits low-frequency background work (triage, summarization, agent side-tasks). It does not suit interactive chat for several simultaneous users. The 27B llama.cpp service, by contrast, runs PARALLEL=2 with true concurrent slots.
|
Consequence: the NPU endpoint is a single lane. It suits low-frequency background work (triage, summarization, agent side-tasks). It does not suit interactive chat for several simultaneous users. The 27B llama.cpp service, by contrast, runs PARALLEL=2 with true concurrent slots.
|
||||||
|
|
||||||
## Test Runbook
|
## Test Runbook
|
||||||
|
|
||||||
This runbook targets a retired endpoint; keep it as the procedure if the NPU is
|
This runbook targets a retired endpoint; keep it as the procedure if the NPU is
|
||||||
ever revived. Do not run large model loads while the production service holds
|
ever revived.
|
||||||
most of the unified pool — 30 GiB exposed to the OS in the 2026-08 reading,
|
|
||||||
**121 GiB** today (`free -g`, read 2026-10-18). Check free RAM first, or stop
|
**Host RAM availability.** The gate is half of system RAM by default - a relic of the
|
||||||
|
install: the endpoint ran on a machine that presented 30 GiB of system RAM; on today's
|
||||||
|
box that ceiling is far larger (live figure: [[Dankclaw System Specs]]). Check free RAM
|
||||||
|
first, or stop
|
||||||
the service the way the bench policy requires (`sudo systemctl stop
|
the service the way the bench policy requires (`sudo systemctl stop
|
||||||
frank-dragoon && sudo systemctl mask frank-dragoon` — self-healing would
|
frank-dragoon && sudo systemctl mask frank-dragoon` — self-healing would
|
||||||
otherwise restart it). The NPU shares the unified pool with everything else on
|
otherwise restart it). The NPU shares the unified pool with everything else on
|
||||||
|
|||||||
@@ -119,5 +119,6 @@ re-download.
|
|||||||
|
|
||||||
- [[Llama Cpp Runtimes]] — which fork ships which custom types
|
- [[Llama Cpp Runtimes]] — which fork ships which custom types
|
||||||
- [[Llama Cpp Code Diff]] — the enum tables and code-level differences
|
- [[Llama Cpp Code Diff]] — the enum tables and code-level differences
|
||||||
- [[frank-dragoon]] — the ftype-115 lock-in in production
|
* [[kingjones-q8agent-rocmfpx]] — the era that served the ftype-115 file, and
|
||||||
|
[[frank-dragoon]] for what runs there now
|
||||||
- [[Llama Cpp Serving Sizing]] — pricing what a payload costs once it loads
|
- [[Llama Cpp Serving Sizing]] — pricing what a payload costs once it loads
|
||||||
|
|||||||
@@ -56,7 +56,10 @@ Lower values leave more GPU memory for KV cache. This reduces swap frequency.
|
|||||||
|
|
||||||
### Swap Space / KV Offload
|
### Swap Space / KV Offload
|
||||||
|
|
||||||
Recent vLLM releases removed the `--swap-space` engine argument — `CacheConfig` on `main` has no `swap_space` field ([source](https://raw.githubusercontent.com/vllm-project/vllm/main/vllm/config/cache.py), read 2026-10-18). Use `--kv-offloading-size` (`kv_offloading_size`, same file) to move KV cache to CPU RAM. In Podman, mount the host cache read-write for KV offload writes. The table below shows historical `--swap-space` guidance as a sizing reference.
|
Current vLLM has no `--swap-space` engine argument, and the CPU KV-offload knob pair
|
||||||
|
is owned by [[RAM CPU Offloading in VLLM]] (that page carries the upstream
|
||||||
|
`CacheConfig` verification). In Podman, mount the host cache read-write for KV offload
|
||||||
|
writes. The table below shows historical `--swap-space` guidance as a sizing reference.
|
||||||
|
|
||||||
| System RAM | Recommended Swap |
|
| System RAM | Recommended Swap |
|
||||||
|------------|------------------|
|
|------------|------------------|
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ Sweep decode across context depth. **Flat** ⇒ attention over history is not
|
|||||||
the cost; the problem is per-token expert movement and KV/attention tuning is
|
the cost; the problem is per-token expert movement and KV/attention tuning is
|
||||||
ruled out entirely. A genuinely context-bound server shows a clear downward
|
ruled out entirely. A genuinely context-bound server shows a clear downward
|
||||||
slope. Record cold vs warm separately — a small gap means the cache is
|
slope. Record cold vs warm separately — a small gap means the cache is
|
||||||
working. Measured on the fp8 expert-offload shape: 12.11 tok/s FLAT from 304
|
working. The canonical flat run (fp8 expert-offload shape, a few hundred to
|
||||||
to 16,095 tokens.
|
sixteen thousand tokens of context) is in [[Tcclaviger Fork Ops]]'s profile.
|
||||||
|
|
||||||
## 2. Duty-cycle arithmetic (the "GPU not fully utilized" answer)
|
## 2. Duty-cycle arithmetic (the "GPU not fully utilized" answer)
|
||||||
|
|
||||||
@@ -161,7 +161,7 @@ of the same RAM, not extra memory.
|
|||||||
## 7. IBS model-access attribution (AMD CPUs)
|
## 7. IBS model-access attribution (AMD CPUs)
|
||||||
|
|
||||||
Real CPU access patterns for mmap'd weights, live, no stop (established on
|
Real CPU access patterns for mmap'd weights, live, no stop (established on
|
||||||
frank-archon, 2026-09-26, ~2.7M attributed samples in 75 s). Reference:
|
[[frank-archon]], 2026-09-26, ~2.7M attributed samples in 75 s). Reference:
|
||||||
`scripts/frank-archon-expert-activity.py` (self-contained dump + sample +
|
`scripts/frank-archon-expert-activity.py` (self-contained dump + sample +
|
||||||
analyze; `--analyze-only`).
|
analyze; `--analyze-only`).
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,9 @@ guesswork.
|
|||||||
each near the target; record `nvidia-smi` used/total plus the boot log's
|
each near the target; record `nvidia-smi` used/total plus the boot log's
|
||||||
`n_slots`/`n_ctx_slot`: shape A = current/cheap, shape B = new demand.
|
`n_slots`/`n_ctx_slot`: shape A = current/cheap, shape B = new demand.
|
||||||
`non-KV = used − (tokens × KiB/token)`; the two rows separate
|
`non-KV = used − (tokens × KiB/token)`; the two rows separate
|
||||||
weights/buffers/graphs from the new demand (a 918 MB projector bills
|
weights/buffers/graphs from the new demand; a projector is billed after the
|
||||||
~1.4 GiB).
|
fit at roughly 1.5x its file size ([[frank-zealot]] Contract has that
|
||||||
|
measurement).
|
||||||
3. **Solve the band:** `KV_tokens ≤ (card − non-KV − headroom_low) /
|
3. **Solve the band:** `KV_tokens ≤ (card − non-KV − headroom_low) /
|
||||||
KiB/token`, round the pool DOWN to a multiple of `PARALLEL × 4096` so every
|
KiB/token`, round the pool DOWN to a multiple of `PARALLEL × 4096` so every
|
||||||
slot gets an equal integer window. Boot and measure; if outside the band,
|
slot gets an equal integer window. Boot and measure; if outside the band,
|
||||||
@@ -54,8 +55,8 @@ First decide which kind of memory is in question:
|
|||||||
| device | kind | read it with |
|
| device | kind | read it with |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| RTX 3090 (Dankclaw) | discrete GDDR6X | `nvidia-smi --query-gpu=memory.total,memory.used,memory.free` |
|
| RTX 3090 (Dankclaw) | discrete GDDR6X | `nvidia-smi --query-gpu=memory.total,memory.used,memory.free` |
|
||||||
| gfx1151 iGPU (Dankclaw) | **UMA** — "VRAM" is host RAM | `/sys/class/drm/card1/device/mem_info_gtt_{total,used}` (114 GiB) vs `mem_info_vram_*` (2 GiB carve-out) |
|
| gfx1151 iGPU (Dankclaw) | **UMA** — "VRAM" is host RAM | `/sys/class/drm/card1/device/mem_info_gtt_{total,used}` vs `mem_info_vram_*`; the aperture and carve-out values are [[Dankclaw System Specs]]'s |
|
||||||
| R9700s (Dankserver) | discrete | `rocm-smi --showmeminfo vram` → 34,208,743,424 B = 32,624 MiB (31.86 GiB) per card, read 2026-10-18 — **not** the 64 GiB "SVM-backed" figure this row once carried ([[Dankserver System Specs]]) |
|
| R9700s (Dankserver) | discrete | `rocm-smi --showmeminfo vram`; the per-card byte/MiB value (and the stale "64 GiB SVM-backed" figure it replaced) is [[Dankserver System Specs]]'s |
|
||||||
|
|
||||||
Per-process truth on NVIDIA:
|
Per-process truth on NVIDIA:
|
||||||
`nvidia-smi --query-compute-apps=pid,process_name,used_memory`. Never add the
|
`nvidia-smi --query-compute-apps=pid,process_name,used_memory`. Never add the
|
||||||
@@ -63,9 +64,10 @@ iGPU's GTT to host RAM as a separate pool; `free -g` is the arbiter for
|
|||||||
co-tenants.
|
co-tenants.
|
||||||
|
|
||||||
- **Engine ledger first.** Halogen prints weights pinned (+ remaining 2 MiB
|
- **Engine ledger first.** Halogen prints weights pinned (+ remaining 2 MiB
|
||||||
contiguous blocks — the honest fragmentation signal: 240 blocks/12.3 GiB
|
contiguous blocks — the honest fragmentation signal: a block census that drops
|
||||||
after reboot vs 475/14.7 GiB before means the model did not come back into
|
across a restart means the model did not come back into the same hole; the
|
||||||
the same hole), device budget, KV pool/working split, "left for everything
|
before/after census this was learned on is that era's, on [[frank-dragoon]]),
|
||||||
|
device budget, KV pool/working split, "left for everything
|
||||||
else". llama.cpp prints them at `llama-model.cpp:1827` (per-backend model buffer)
|
else". llama.cpp prints them at `llama-model.cpp:1827` (per-backend model buffer)
|
||||||
and `llama-context.cpp:692` (compute buffer) on the era's build; on today's
|
and `llama-context.cpp:692` (compute buffer) on the era's build; on today's
|
||||||
`master` the same `LLAMA_LOG_INFO` lines sit at `llama-model.cpp:2009`
|
`master` the same `LLAMA_LOG_INFO` lines sit at `llama-model.cpp:2009`
|
||||||
@@ -83,13 +85,13 @@ co-tenants.
|
|||||||
graph/compute pool).
|
graph/compute pool).
|
||||||
- **Traps:** mmap'd PLE is reclaimable page cache; `-ot` makes it pinned —
|
- **Traps:** mmap'd PLE is reclaimable page cache; `-ot` makes it pinned —
|
||||||
"move layers to the card" converts reclaimable cache into device memory and
|
"move layers to the card" converts reclaimable cache into device memory and
|
||||||
frees nothing for co-tenants. A served model's footprint ≠ weight size
|
frees nothing for co-tenants. A served model's footprint is not its weight
|
||||||
(a retired frank-zealot shape: 22.6 of 24.1 GiB for an 11.29 GiB model; the card
|
size: the MiMo Q5_K_M era booted a 6.40 GiB payload to **20,530 MiB used** of the
|
||||||
today reads 24,576 MiB = 24.0 GiB total, `nvidia-smi --query-gpu=memory.total`,
|
3090's addressable 24,576 — the Eras row and its addressable ≠ advertised law are on
|
||||||
2026-10-18, and the deployed payload is the PQ2_0 pair
|
[[frank-zealot]]. What the card reports used is weights + KV + compute buffers +
|
||||||
[[frank-zealot]]). Do the capacity
|
projector, never weights alone. Do
|
||||||
subtraction before designing: 12 attn layers × 1.62 GiB + 200k f16 KV =
|
the capacity subtraction before designing, on the card number the owner page
|
||||||
28.6 GiB > 24.1 GiB usable → KV-in-VRAM on that pair only reaches ~64k.
|
quotes, not the advertised one.
|
||||||
- **Context lengths: derive, never remember.** `llama-bench` computes
|
- **Context lengths: derive, never remember.** `llama-bench` computes
|
||||||
`n_ctx = n_prompt + n_gen + n_depth` (defaults 512/128/0, type_k/v F16,
|
`n_ctx = n_prompt + n_gen + n_depth` (defaults 512/128/0, type_k/v F16,
|
||||||
flash_attn AUTO, split_mode LAYER). `-p 512,16384 -n 64` = contexts
|
flash_attn AUTO, split_mode LAYER). `-p 512,16384 -n 64` = contexts
|
||||||
@@ -112,10 +114,10 @@ them from the binary (`llama-server --help`) before sizing on them.
|
|||||||
**State law** (compute before trusting any cap): a state is the serialized KV
|
**State law** (compute before trusting any cap): a state is the serialized KV
|
||||||
of the whole sequence + constant recurrent state + the draft context's KV:
|
of the whole sequence + constant recurrent state + the draft context's KV:
|
||||||
`per_token = 2 × n_full_attn_layers × n_kv_heads × head_dim × bytes (K and V) +
|
`per_token = 2 × n_full_attn_layers × n_kv_heads × head_dim × bytes (K and V) +
|
||||||
draft_per_token`. Measured on frank-medium (qwen3.5 hybrid, f16, MTP draft):
|
draft_per_token`. The worked qwen35-hybrid instance of that formula (full layer
|
||||||
16×4×256×2×2 = 64 KiB/token + 4 KiB draft = **68 KiB/token**; a full
|
count, f16 KV, MTP draft) and the slot-size table it prices are on
|
||||||
196,608-token slot state ≈ 12.8 GiB. Cross-check against the journal's
|
[[frank-medium-llamacpp-dflash2]]; cross-check any such arithmetic against the
|
||||||
`prompt state size` lines — the two must agree.
|
journal's `prompt state size` lines — the two must agree.
|
||||||
|
|
||||||
**The journal is the instrument:** `exceeds cache size limit … skipping` =
|
**The journal is the instrument:** `exceeds cache size limit … skipping` =
|
||||||
cap binding in production; `making room … removing oldest` / `cache size
|
cap binding in production; `making room … removing oldest` / `cache size
|
||||||
@@ -162,13 +164,13 @@ Only the charlie12345/ROCmFPX build-qwen38 (PR #27742 qwen4exp merged) takes
|
|||||||
it; CIRU, upstream and stock builds do not. Validate live: load with
|
it; CIRU, upstream and stock builds do not. Validate live: load with
|
||||||
`--flash-attn on`, health 200, a real completion finishing `"stop"`, journal
|
`--flash-attn on`, health 200, a real completion finishing `"stop"`, journal
|
||||||
clean of `GGML_ASSERT`/`cudaMalloc`/`missing tensor`, and flash-attn engaged
|
clean of `GGML_ASSERT`/`cudaMalloc`/`missing tensor`, and flash-attn engaged
|
||||||
in the timings. Context cap for full-model residency on that shape stayed
|
in the timings. The context cap that build reached for full-model residency is
|
||||||
32,768.
|
part of that era's record on [[frank-dragoon]].
|
||||||
|
|
||||||
## Related
|
## Related
|
||||||
|
|
||||||
- [[GGUF Compatibility]] — what a payload is before it is priced
|
- [[GGUF Compatibility]] — what a payload is before it is priced
|
||||||
- [[frank-zealot]] — the two-boot priced shape of the retired MiMo era (live shape today: [[frank-zealot]])
|
- [[frank-zealot]] — the endpoint whose Eras rows are the two-boot priced shapes this method produced
|
||||||
- [[frank-medium-llamacpp-dflash2]] — where the 68 KiB/token datum was measured
|
- [[frank-medium-llamacpp-dflash2]] — the state-law worked example behind section 3
|
||||||
- [[DFlash DSpark Speculative Decoding]] — the spec A/B protocol on llama.cpp
|
- [[DFlash DSpark Speculative Decoding]] — the spec A/B protocol on llama.cpp
|
||||||
- [[Dual-R9700-Cooperation]] / [[x4-pair-experiment]] — the multi-device side
|
- [[Dual-R9700-Cooperation]] / [[x4-pair-experiment]] — the multi-device side
|
||||||
|
|||||||
@@ -40,9 +40,9 @@ curl -s <health> # then a REAL completion
|
|||||||
```
|
```
|
||||||
|
|
||||||
Deploy caveat: "healthy after Ns" = systemd ACTIVE, not model LOADED —
|
Deploy caveat: "healthy after Ns" = systemd ACTIVE, not model LOADED —
|
||||||
confirm with a real `/v1/chat/completions`. RTX 3090 (Ampere) has no
|
confirm with a real `/v1/chat/completions`. On Ampere an FP8 file buys memory
|
||||||
FP8/FP4 tensor cores: FP8 weights run via upcast but must still fit; choose
|
and no compute ([[Quantization by Hardware Architecture]]): choose the quant by
|
||||||
quant by size fit, then accept the compute path the card supports. Before
|
size fit, then accept the compute path the card supports. Before
|
||||||
choosing a smaller quant, state WHICH of the two you are buying — headroom,
|
choosing a smaller quant, state WHICH of the two you are buying — headroom,
|
||||||
or a design change (a smaller quant does not change what the runtime can
|
or a design change (a smaller quant does not change what the runtime can
|
||||||
express; per-tensor cross-device placement stays refused under
|
express; per-tensor cross-device placement stays refused under
|
||||||
@@ -60,8 +60,8 @@ express; per-tensor cross-device placement stays refused under
|
|||||||
## 3. Fetch and verify (HF payloads)
|
## 3. Fetch and verify (HF payloads)
|
||||||
|
|
||||||
**Inventory by QUANT NAME, never by extension** — large quants ship as
|
**Inventory by QUANT NAME, never by extension** — large quants ship as
|
||||||
`.partNofM` fragments (Q4_K_M = 37.00+37.00+36.97 GiB), so an
|
`.partNofM` fragments, so an `endswith(".gguf")` filter makes a whole rung look
|
||||||
`endswith(".gguf")` filter makes Q4_K_S look nonexistent. Check both
|
nonexistent (AGENTS.md carries the worked fragment ledger). Check both
|
||||||
mradermacher repos (`…-i1-GGUF` imatrix, `…-GGUF` plain) and the model's own
|
mradermacher repos (`…-i1-GGUF` imatrix, `…-GGUF` plain) and the model's own
|
||||||
repo; the tree API's `blobs=true` gives `lfs.oid` per file. Gated mirrors
|
repo; the tree API's `blobs=true` gives `lfs.oid` per file. Gated mirrors
|
||||||
return 403 even with a valid token until the account accepts the gate —
|
return 403 even with a valid token until the account accepts the gate —
|
||||||
@@ -150,7 +150,7 @@ recoverable, drift is not.
|
|||||||
entry in `serverAppConfigs-docs/log.md`.
|
entry in `serverAppConfigs-docs/log.md`.
|
||||||
2. `~/.omp/agent/models.yml`: `contextWindow` must equal the REAL per-slot
|
2. `~/.omp/agent/models.yml`: `contextWindow` must equal the REAL per-slot
|
||||||
context — llama.cpp logs `n_ctx_slot` per prompt (`--parallel N` divides
|
context — llama.cpp logs `n_ctx_slot` per prompt (`--parallel N` divides
|
||||||
the pool; e.g. 262144 native / 2 slots = 131072 per slot); vLLM reports
|
the pool; e.g. a 524288 pool over 2 slots = 262144 per slot); vLLM reports
|
||||||
`max-model-len` and its concurrency line. Overselling causes silent
|
`max-model-len` and its concurrency line. Overselling causes silent
|
||||||
client-side overflow or a discovered-wall 400. Also `maxTokens` vs the
|
client-side overflow or a discovered-wall 400. Also `maxTokens` vs the
|
||||||
engine's cap, `input` capabilities (text/image), and
|
engine's cap, `input` capabilities (text/image), and
|
||||||
@@ -252,12 +252,10 @@ small/fast + image roles at the new endpoint; move the vision role WITH the
|
|||||||
vision tower (one owner per capability). `shared/homepage/services.json`: a
|
vision tower (one owner per capability). `shared/homepage/services.json`: a
|
||||||
card per endpoint, probed from the monitor's own host. Prometheus: only add
|
card per endpoint, probed from the monitor's own host. Prometheus: only add
|
||||||
a job if the runtime actually exposes Prometheus text — and re-measure rather
|
a job if the runtime actually exposes Prometheus text — and re-measure rather
|
||||||
than repeat, because that answer moves. This bullet once said halogen serves
|
than repeat, because that answer moves: halogen's HTTP surface has grown twice
|
||||||
`/health`, `/cache`, `/v1/*` "and nothing else"; measured 2026-10-18 on
|
since this page was written, and the endpoint list that matters for a scrape
|
||||||
Dankclaw, `curl -s http://127.0.0.1:7770/metrics` returns Prometheus text
|
target — including whether `/metrics` answers — is [[frank-dragoon]]'s wire
|
||||||
(`# HELP llamacpp:prompt_tokens_total …`, content-type
|
contract.
|
||||||
`text/plain; version=0.0.4`) while an invented path 404s — so the surface has
|
|
||||||
grown and a scrape target is expressible again.
|
|
||||||
|
|
||||||
**4. Cutover, then verify by driving it.** `deploy.sh <target> --service
|
**4. Cutover, then verify by driving it.** `deploy.sh <target> --service
|
||||||
<large> --service <small>` (order matters); per endpoint: `/health`,
|
<large> --service <small>` (order matters); per endpoint: `/health`,
|
||||||
@@ -265,10 +263,10 @@ grown and a scrape target is expressible again.
|
|||||||
`reasoning_content`, a `tools` request returns `tool_calls`, an image
|
`reasoning_content`, a `tools` request returns `tool_calls`, an image
|
||||||
request is answered (or refused with a named reason), the runtime's own
|
request is answered (or refused with a named reason), the runtime's own
|
||||||
speculation counters move, and the unit is `enabled` and `active`. All three LLM
|
speculation counters move, and the unit is `enabled` and `active`. All three LLM
|
||||||
endpoints are **root** units today (`User=dank` + `WantedBy=multi-user.target` —
|
endpoints are **root** units today (`scripts/frank-archon.service`,
|
||||||
`scripts/frank-archon.service:30,71`, `scripts/frank-dragoon.service:8,31`,
|
`scripts/frank-dragoon.service`, `scripts/frank-zealot.service`), so linger is
|
||||||
`scripts/frank-zealot.service:8,26`), so linger is not what gates them; linger
|
not what gates them; linger matters for rootless quadlets. Read the engine's boot
|
||||||
matters for rootless quadlets. Read the engine's boot ledger for a silent clamp. Finally spend one
|
ledger for a silent clamp. Finally spend one
|
||||||
real request through the harness per changed role — routing labels lie; the
|
real request through the harness per changed role — routing labels lie; the
|
||||||
servers' own journals do not.
|
servers' own journals do not.
|
||||||
|
|
||||||
@@ -285,4 +283,5 @@ predecessor "stopped" (the port race above).
|
|||||||
- [[Llama Cpp Serving Sizing]] — pricing the shape once it loads
|
- [[Llama Cpp Serving Sizing]] — pricing the shape once it loads
|
||||||
- [[RDNA4 MoE Expert Offload VRAM Budget]] — vLLM-side fit arithmetic
|
- [[RDNA4 MoE Expert Offload VRAM Budget]] — vLLM-side fit arithmetic
|
||||||
- [[LLM Bench Windows and Measurement]] — measuring the new deployment
|
- [[LLM Bench Windows and Measurement]] — measuring the new deployment
|
||||||
- [[frank-archon]] — the retired tcclaviger vLLM endpoint (2026-09-29 → 10-05); the live Dankserver endpoint is [[frank-archon]]
|
* [[frank-archon]] — the live Dankserver endpoint; the tcclaviger vLLM era
|
||||||
|
(2026-09-29 → 10-05) is a row in its Eras table
|
||||||
|
|||||||
@@ -65,13 +65,11 @@ LPDDR5X on the Strix Halo — 128 GB LPDDR5x-8000 on a 256-bit bus,
|
|||||||
streaming loses by construction and no tuning rescues it; doubling the link
|
streaming loses by construction and no tuning rescues it; doubling the link
|
||||||
only doubles a losing number.**
|
only doubles a losing number.**
|
||||||
|
|
||||||
Worked example (Dankclaw 2026-09-16): Gen4 x4 measured H2D **6.72 / D2H 6.60
|
Worked example: the Dankclaw Gen4 x4 run of 2026-09-16 — measured H2D/D2H
|
||||||
GB/s** (85 % of spec) — pinned H2D ≈ async, pageable within 1 %, i.e.
|
rates, the 3 MiB slab cost, and the streaming-vs-compute comparison it decided
|
||||||
link-limited not staging-limited. A 3 MiB slab (the expert-streaming
|
— is recorded on [[x4-pair-experiment]] §The link, measured. Read it once and
|
||||||
granularity) = 474 µs. A3B MoE at Q4_K_M (~1.70 GiB active/token) → 272
|
apply the rule above: on that link the streaming design lost by 3–5x, and the
|
||||||
ms/token ⇒ **3.7 tok/s** (4.6 with 20 % resident) vs measured **20.46 tok/s**
|
x8 ceiling would only have halved the loss.
|
||||||
with experts computed on the CPU, 25–26.5 on the iGPU. The streaming design
|
|
||||||
loses 3–5x.
|
|
||||||
|
|
||||||
## 3. Measure the link: two probes, same mechanics
|
## 3. Measure the link: two probes, same mechanics
|
||||||
|
|
||||||
@@ -150,9 +148,9 @@ int main(int argc, char **argv) {
|
|||||||
(the usual "pageable costs 2x" rule does not apply at this link).
|
(the usual "pageable costs 2x" rule does not apply at this link).
|
||||||
- Small-transfer penalty (2.345 MiB: ~106 µs vs ~78 µs ideal, ~21 %) is
|
- Small-transfer penalty (2.345 MiB: ~106 µs vs ~78 µs ideal, ~21 %) is
|
||||||
per-transfer overhead — recoverable only by BATCHING transfers, not by a
|
per-transfer overhead — recoverable only by BATCHING transfers, not by a
|
||||||
faster link. (Dankserver 2026-09-29: bulk 22.7 GB/s at the 2.344 MiB slab =
|
faster link. The engine-vs-wire version of that reading on Dankserver
|
||||||
91 % of Gen5 x8, while the engine's effective read path ran ~9.5 GB/s — the
|
(bulk slab rate against the engine's effective gather rate, same
|
||||||
gap is the fork's gather software path, not the wire.)
|
granularity) is [[frank-archon]]'s tcclaviger-era record.
|
||||||
- Both GPUs symmetric ⇒ no cross-device rebalance is available; measure both.
|
- Both GPUs symmetric ⇒ no cross-device rebalance is available; measure both.
|
||||||
- Don't quote a derived line from inside a probe without hand-checking it —
|
- Don't quote a derived line from inside a probe without hand-checking it —
|
||||||
a printf format/argument mismatch in one of these printed a nonsense
|
a printf format/argument mismatch in one of these printed a nonsense
|
||||||
@@ -186,7 +184,8 @@ sudo lspci -vv -s <bridge> | grep AtomicOpsCap # want Routing+
|
|||||||
`Routing-` is a read-only hardware capability. Typical AM5 layout: one x16
|
`Routing-` is a read-only hardware capability. Typical AM5 layout: one x16
|
||||||
slot on CPU root ports (atomics fine), the rest behind the chipset (usually
|
slot on CPU root ports (atomics fine), the rest behind the chipset (usually
|
||||||
not). Bandwidth for TP is small anyway: ~10 MB per token-step for a 27B at
|
not). Bandwidth for TP is small anyway: ~10 MB per token-step for a 27B at
|
||||||
batch 4 ≈ 1.4 ms at Gen4 x4 — compute-bound, not interconnect-bound.
|
batch 4 is a millisecond-scale figure at x4 — compute-bound, not
|
||||||
|
interconnect-bound (full derivation: [[Dual-R9700-Cooperation]] §Bandwidth).
|
||||||
|
|
||||||
**Probe matrix (bare 2-rank `torch.distributed`, one process per GPU, 25 s PG
|
**Probe matrix (bare 2-rank `torch.distributed`, one process per GPU, 25 s PG
|
||||||
timeout) — one probe answers several design questions:**
|
timeout) — one probe answers several design questions:**
|
||||||
@@ -215,13 +214,12 @@ reporting an outage (`gitea` vs `gitea-server`).
|
|||||||
|
|
||||||
1. CPU-attached M.2 → PCIe x4 riser (~$30) — puts the card on the CPU root
|
1. CPU-attached M.2 → PCIe x4 riser (~$30) — puts the card on the CPU root
|
||||||
complex; x4 suffices for TP.
|
complex; x4 suffices for TP.
|
||||||
2. Board whose CPU x16 bifurcates x8/x8 (done 2026-09-20 on dankserver — both
|
2. Board whose CPU x16 bifurcates x8/x8 (done 2026-09-20 on dankserver — the
|
||||||
R9700s on root ports `00:01.1`/`00:01.3`, every bridge `Routing+`, both
|
per-device chain census, including both endpoints reading `ReqEn+`, is
|
||||||
endpoints `ReqEn+`). Re-checked 2026-10-18 without root: both root ports
|
[[Dual-R9700-Cooperation]]'s). Re-checked 2026-10-18 without root: both root
|
||||||
report `current_link_width=8` at `32.0 GT/s`
|
ports report `current_link_width=8` at `32.0 GT/s`
|
||||||
(`/sys/bus/pci/devices/0000:00:01.{1,3}/current_link_width`), and the live
|
(`/sys/bus/pci/devices/0000:00:01.{1,3}/current_link_width`), and the live
|
||||||
engine states direct P2P between the cards
|
engine states direct P2P between the cards.
|
||||||
([[Dual-R9700-Cooperation]]).
|
|
||||||
3. llama.cpp `--split-mode layer` — no collectives at all ([[Llama Cpp Multi-Device Splits]]); costs the GGUF conversion plus paged attention /
|
3. llama.cpp `--split-mode layer` — no collectives at all ([[Llama Cpp Multi-Device Splits]]); costs the GGUF conversion plus paged attention /
|
||||||
continuous batching / spec decode.
|
continuous batching / spec decode.
|
||||||
4. Independent TP=1 replicas + routing proxy — cards never share one model.
|
4. Independent TP=1 replicas + routing proxy — cards never share one model.
|
||||||
|
|||||||
@@ -43,8 +43,16 @@ state, verified against the live journal and output smoke tests
|
|||||||
the mismatch (`resolve_fused_ops: Flash Attention enabled`) via the
|
the mismatch (`resolve_fused_ops: Flash Attention enabled`) via the
|
||||||
GGML_CUDA_FA_ALL_QUANTS rebuild — see "FA-all-quants rebuild" below.
|
GGML_CUDA_FA_ALL_QUANTS rebuild — see "FA-all-quants rebuild" below.
|
||||||
- Pool `262144`, `PARALLEL=1`, live `n_ctx_slot = 262144`.
|
- Pool `262144`, `PARALLEL=1`, live `n_ctx_slot = 262144`.
|
||||||
- MTP: standalone draft head, acceptance 0.83 then 0.75, mean len
|
* MTP: standalone draft head, acceptance 0.83 then 0.75, mean len 4.0-4.3,
|
||||||
4.0-4.3, per-position ~0.86/0.71/0.71/0.71.
|
per-position ~0.86/0.71/0.71/0.71 — stronger at every position than the old bundled
|
||||||
|
head, which measured 0.739/0.554/0.427/0.340.
|
||||||
|
- Spec chain as deployed: `--spec-draft-n-max 4` on the standalone draft, with
|
||||||
|
the `--spec-default` ngram-mod fallback at n_match 24 / n_min 48 / n_max 64
|
||||||
|
(the preset that survived the DSpark/DFlash retirements —
|
||||||
|
[[qwen3.8-spec-matrix]]).
|
||||||
|
- Batch 8192 / ubatch 256, `--direct-io`, `--fit off`, `--gpu-layers all`. The
|
||||||
|
pi `models.json` declared 262144 (`contextWindow = maxTokens`, the house
|
||||||
|
convention of that era).
|
||||||
- Head GPU side: **ROCm0** (no `--device` flag; HIP registers before
|
- Head GPU side: **ROCm0** (no `--device` flag; HIP registers before
|
||||||
Vulkan).
|
Vulkan).
|
||||||
- Worker steady state: 23854/24576 MiB used, ~273 MiB free (tight but
|
- Worker steady state: 23854/24576 MiB used, ~273 MiB free (tight but
|
||||||
@@ -215,8 +223,11 @@ head env ([[frank-dragoon]]).
|
|||||||
faster prefill, ~3% slower decode (measured on this box).
|
faster prefill, ~3% slower decode (measured on this box).
|
||||||
3. **Pin `--tensor-split 1,1`.** The default split is proportional to
|
3. **Pin `--tensor-split 1,1`.** The default split is proportional to
|
||||||
*reported free memory*: the Strix reports up to 96 GiB (GTT) vs the
|
*reported free memory*: the Strix reports up to 96 GiB (GTT) vs the
|
||||||
3090's 24 GB, so the default lands ~20/80 on the slow device (verified
|
3090's 24 GB, so the default lands ~20/80 on the slow device. 1,1 = 50/50 =
|
||||||
with a 4B smoke test). 1,1 = 50/50 = balanced per-layer latency.
|
balanced per-layer latency. The 2026-08-15 4B smoke test that proved it
|
||||||
|
(production untouched): at a 0.2/0.8 split only 4 of 36 layers reached the
|
||||||
|
3090, and at a real split worker VRAM rose ~819 MiB with 95 t/s prefill /
|
||||||
|
58.8 t/s decode on the tiny model; link RTT ~0.3–0.5 ms.
|
||||||
4. **`-dio` on the head.** Large model + RPC hangs at load without direct
|
4. **`-dio` on the head.** Large model + RPC hangs at load without direct
|
||||||
I/O.
|
I/O.
|
||||||
5. **RPC is unauthenticated and unencrypted.** LAN only. The worker binds
|
5. **RPC is unauthenticated and unencrypted.** LAN only. The worker binds
|
||||||
|
|||||||
@@ -147,12 +147,14 @@ cut to GPTQ-w4 for the 3090 is a bench experiment that needs no new
|
|||||||
hardware; EXL3 (`convert.py` on the 3090, exllama serve) is the
|
hardware; EXL3 (`convert.py` on the 3090, exllama serve) is the
|
||||||
quality-per-bit extreme of the same menu.
|
quality-per-bit extreme of the same menu.
|
||||||
Caveats before any swap: the serving contract (OpenAI server,
|
Caveats before any swap: the serving contract (OpenAI server,
|
||||||
`reasoning_content`, vision mmproj, compaction-hub window
|
`reasoning_content`, vision mmproj, and the compaction-hub window the endpoint
|
||||||
200,704 ×2 slots) must be met by the challenger runtime, and the
|
declares in its Current shape — [[frank-zealot]]) must be met by the challenger
|
||||||
24 GB card runs ONE server — benching follows the stop-and-mask law.
|
runtime, and the 24 GB card runs ONE server — benching follows the stop-and-mask
|
||||||
|
law.
|
||||||
|
|
||||||
#### Worked example — the frank-archon w4dn8 recipe ported to the 3090
|
#### Worked example — the frank-archon w4dn8 recipe ported to the 3090
|
||||||
(audit 2026-10-08, target `Qwen3.6-35B-A3B`)
|
(audit 2026-10-08, target `Qwen3.6-35B-A3B`; sized at that date's hub shape —
|
||||||
|
the window history is [[frank-zealot]]'s Eras table)
|
||||||
**The methodology ports; the encoding must be translated.** llama.cpp
|
**The methodology ports; the encoding must be translated.** llama.cpp
|
||||||
decodes no GPTQ — the recipe re-expresses on GGUF-native terms:
|
decodes no GPTQ — the recipe re-expresses on GGUF-native terms:
|
||||||
imatrix on our corpora (replaces the radiance grams; runs the 65 GiB
|
imatrix on our corpora (replaces the radiance grams; runs the 65 GiB
|
||||||
@@ -253,8 +255,6 @@ top-8**, moe_intermediate 512, hidden 2048, MTP ×1, 262k ctx, vocab
|
|||||||
- Repo: `scripts/convert-swift15-w4dn8.sh`,
|
- Repo: `scripts/convert-swift15-w4dn8.sh`,
|
||||||
`scripts/recipes/qwen4exp-swift15-w4dn8-i8-hc8m.recipe`,
|
`scripts/recipes/qwen4exp-swift15-w4dn8-i8-hc8m.recipe`,
|
||||||
`scripts/kld-gate-swift15.sh`, `scripts/build-llama-rdna4.sh`,
|
`scripts/kld-gate-swift15.sh`, `scripts/build-llama-rdna4.sh`,
|
||||||
`scripts/build-kairic-edge-gfx1151.sh`, [[frank-dragoon]],
|
`scripts/build-kairic-edge-gfx1151.sh`; endpoints [[frank-archon]],
|
||||||
[[frank-dragoon]], [[qwen3.8-strix-optimizations]],
|
[[frank-dragoon]], [[frank-zealot]]; method [[qwen3.8-strix-optimizations]]
|
||||||
[[frank-archon]],
|
and [[GGUF Compatibility]].
|
||||||
[[frank-zealot]],
|
|
||||||
[[frank-dragoon]], [[GGUF Compatibility]].
|
|
||||||
|
|||||||
@@ -108,9 +108,10 @@ Use ROCmFP4 only with the ROCmFPX fork of llama.cpp. Upstream llama.cpp cannot r
|
|||||||
|
|
||||||
## Choices for This Project
|
## Choices for This Project
|
||||||
|
|
||||||
### Dankserver (RTX 3090, 24 GB, Ampere)
|
### The RTX 3090 (24 GB, Ampere) — frank-zealot's card
|
||||||
|
|
||||||
The RTX 3090 has no native FP8 or FP4 tensor cores. Use:
|
The 3090 has no native FP8 or FP4 tensor cores. It has sat in Dankclaw since
|
||||||
|
2026-09-16; [[frank-zealot]]'s Eras table records the move off Dankserver. Use:
|
||||||
|
|
||||||
| Ranking | Format | Why |
|
| Ranking | Format | Why |
|
||||||
|---------|--------|-----|
|
|---------|--------|-----|
|
||||||
@@ -121,13 +122,17 @@ The RTX 3090 has no native FP8 or FP4 tensor cores. Use:
|
|||||||
|
|
||||||
### Dankclaw (Strix Halo gfx1151, RDNA 3.5)
|
### Dankclaw (Strix Halo gfx1151, RDNA 3.5)
|
||||||
|
|
||||||
RDNA 3.5 has no native FP8 tensor cores. The APU shares memory. The active Ling-3.0-flash service runs vLLM-ROCm with the AMD Quark INT4 (W4A16) format (the jcbtc CIRU Strix-native bundle). INT4 weights keep the 124B model inside the 96 GiB frame buffer with a full-precision KV cache.
|
RDNA 3.5 has no native FP8 tensor cores and the APU shares its memory, so the
|
||||||
|
GPU budget is the GTT aperture and every live figure on the box is
|
||||||
|
[[Dankclaw System Specs]]. What serves here today is [[frank-dragoon]]: a
|
||||||
|
vendor `.hgn` checkpoint, a format this page cannot rank because no public
|
||||||
|
quantizer exists for it ([[Quantization Production]]).
|
||||||
|
|
||||||
| Ranking | Format | Why |
|
| Ranking | Format | Why |
|
||||||
|---------|--------|-----|
|
|---------|--------|-----|
|
||||||
| 1 | INT4 W4A16 (Quark/vLLM) | active; fits 96 GiB; native ROCm kernels; concurrency |
|
| 1 | `.hgn` (deployed) | the halogen engine's own format; production door is closed |
|
||||||
| 2 | MXFP4 (Quark) | same-bit, higher accuracy; beta on gfx1151 (A/B experiment) |
|
| 2 | GGUF K/I quants, K_P blends | the only self-produced option on this card ([[Quantization Production]]) |
|
||||||
| 3 | GGUF Q4_K_M / Q8_0 | works with upstream llama.cpp only |
|
| 3 | INT4 W4A16 (Quark) / MXFP4 (Quark) | the retired Ling-3.0-flash vLLM era, measured under the firmware-VGM frame buffer: [[ling-3.0-flash-trial]] |
|
||||||
| 4 | FP8 (vLLM) | software emulation; memory savings only; no compute win |
|
| 4 | FP8 (vLLM) | software emulation; memory savings only; no compute win |
|
||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|||||||
@@ -11,9 +11,19 @@ timestamp: 2026-08-28
|
|||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
vLLM uses CPU RAM and swap space to extend GPU memory capacity. This allows larger models to run on GPUs with limited VRAM. vLLM does not offload model weights to CPU. Instead, vLLM moves KV cache data between GPU and CPU.
|
Stock vLLM offloads **KV pages**, not weights: the scheduler moves KV cache between GPU
|
||||||
|
and CPU. That is the upstream behaviour and it is NOT the whole story on our hosts — the
|
||||||
|
tcclaviger/R4D fork ran a real **weight** offload (`--enable-expert-offload`, tiered
|
||||||
|
expert placement, a pinned host pool per rank), which is how a 147 GiB MoE served from a
|
||||||
|
246 GiB box: [[RDNA4 MoE Expert Offload VRAM Budget]] and the tcclaviger era row of
|
||||||
|
[[frank-archon]]. First-hand in-repo evidence outranks a generic upstream claim about our
|
||||||
|
own hosts ([[Model Swap and Rollback]] §10).
|
||||||
|
|
||||||
> **Current vLLM note:** Recent vLLM releases removed the `--swap-space` engine argument. CPU KV-cache offloading now uses `--kv-offloading-size`. See the parameters below for details.
|
> **Verified 2026-10-19 against `vllm/config/cache.py` on `main`:** there is no
|
||||||
|
> `swap_space` field — `--swap-space` is gone from current engine args. CPU KV offload is
|
||||||
|
> `--kv-offloading-size`, and it activates **only** together with `--kv-offloading-backend`
|
||||||
|
> (default `native`); both fields live in that one file. This page is the fleet's owner of
|
||||||
|
> that knob contract — other pages link here instead of restating it.
|
||||||
|
|
||||||
## How CPU Offloading Works
|
## How CPU Offloading Works
|
||||||
|
|
||||||
@@ -42,9 +52,12 @@ This parameter controls the fraction of GPU memory used for KV cache.
|
|||||||
|
|
||||||
Lower values leave more GPU memory for model weights. Higher values allow more concurrent requests but increase swap frequency.
|
Lower values leave more GPU memory for model weights. Higher values allow more concurrent requests but increase swap frequency.
|
||||||
|
|
||||||
### swap_space (removed) / kv-offloading-size (current)
|
### swap_space (removed) / kv-offloading-size + kv-offloading-backend (current)
|
||||||
|
|
||||||
The `--swap-space` argument was removed from current vLLM engine args. Use `--kv-offloading-size` instead. The table below describes the historical `--swap-space` values for reference.
|
`--swap-space` no longer exists in current engine args (verified above); the live pair is
|
||||||
|
`--kv-offloading-size` with `--kv-offloading-backend`, and offload stays off until the size
|
||||||
|
is set. The table below is the historical `--swap-space` sizing guidance, kept as a sizing
|
||||||
|
reference only.
|
||||||
|
|
||||||
| Value | Description |
|
| Value | Description |
|
||||||
|-------|-------------|
|
|-------|-------------|
|
||||||
@@ -103,6 +116,9 @@ This parameter sets the KV cache data type.
|
|||||||
|
|
||||||
## Memory Configuration Examples
|
## Memory Configuration Examples
|
||||||
|
|
||||||
|
All three examples carry the retired `--swap-space` syntax and are kept as sizing
|
||||||
|
references; the live knob pair is named above.
|
||||||
|
|
||||||
### Small Model on Single GPU
|
### Small Model on Single GPU
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -157,7 +173,7 @@ WARNING scheduler.py: Sequence group 0 is preempted by PreemptionMode.RECOMPUTE
|
|||||||
If you see frequent preemptions:
|
If you see frequent preemptions:
|
||||||
|
|
||||||
1. Increase `gpu_memory_utilization`
|
1. Increase `gpu_memory_utilization`
|
||||||
2. Increase `swap_space`
|
2. Raise the KV offload budget (`--kv-offloading-size`, with `--kv-offloading-backend`)
|
||||||
3. Decrease `max_num_seqs`
|
3. Decrease `max_num_seqs`
|
||||||
4. Increase `tensor_parallel_size`
|
4. Increase `tensor_parallel_size`
|
||||||
5. Increase `max_model_len` to match actual usage
|
5. Increase `max_model_len` to match actual usage
|
||||||
@@ -169,7 +185,8 @@ If you see frequent preemptions:
|
|||||||
- Reduce `max_num_seqs` to limit concurrent requests
|
- Reduce `max_num_seqs` to limit concurrent requests
|
||||||
- Disable CUDA graphs with `--enforce-eager` to save memory
|
- Disable CUDA graphs with `--enforce-eager` to save memory
|
||||||
- Set `compilation_config.cudagraph_capture_sizes` to smaller values
|
- Set `compilation_config.cudagraph_capture_sizes` to smaller values
|
||||||
- Use `--kv-cache-memory` to skip memory profiling
|
- Set `--kv-cache-memory-bytes` to pin the KV budget instead of letting the profiler guess
|
||||||
|
(the flag our own `scripts/patches/gpu_worker-kv-cap.patch` reads)
|
||||||
- Limit multi-modal inputs with `limit_mm_per_prompt`
|
- Limit multi-modal inputs with `limit_mm_per_prompt`
|
||||||
|
|
||||||
## Environment Variables
|
## Environment Variables
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ timestamp: 2026-10-05T00:00:00-07:00
|
|||||||
|
|
||||||
# RDNA4 Container Serving
|
# RDNA4 Container Serving
|
||||||
|
|
||||||
Bring-up path for Dankserver (2x Radeon AI PRO R9700, gfx1201, 31.86 GiB each =
|
Bring-up path for Dankserver (2x Radeon AI PRO R9700, gfx1201 — card count,
|
||||||
**63.7 GiB real VRAM**, 246 GiB RAM, 7700X) with
|
per-card VRAM and host RAM are [[Dankserver System Specs]]'s) with
|
||||||
`docker.io/tcclaviger/vllm` (vLLM 0.29.0.dev, GLM/Qwen-specialised RDNA4 build
|
`docker.io/tcclaviger/vllm` (vLLM 0.29.0.dev, GLM/Qwen-specialised RDNA4 build
|
||||||
with native MoE quant kernels and a first-class expert offload planner). The
|
with native MoE quant kernels and a first-class expert offload planner). The
|
||||||
tuning history and current deployed shape live in
|
tuning history and current deployed shape live in
|
||||||
@@ -155,7 +155,9 @@ podman run -d --name <ctr> --ipc=host --ulimit memlock=-1:-1 \
|
|||||||
|
|
||||||
## 5. Memory budgeting: the levers are not where they look
|
## 5. Memory budgeting: the levers are not where they look
|
||||||
|
|
||||||
The planner builds `budget = total × util`, subtracts a KV reserve, and gives
|
Every figure in this section is a tcclaviger-era boot on the port that is
|
||||||
|
[[frank-archon]]'s today; the laws they teach are general. The planner builds
|
||||||
|
`budget = total × util`, subtracts a KV reserve, and gives
|
||||||
the REMAINDER to the expert arena. Consequences, all measured:
|
the REMAINDER to the expert arena. Consequences, all measured:
|
||||||
|
|
||||||
- **`--gpu-memory-utilization` grows the ARENA, not the KV pool** (KV stayed
|
- **`--gpu-memory-utilization` grows the ARENA, not the KV pool** (KV stayed
|
||||||
@@ -163,11 +165,14 @@ the REMAINDER to the expert arena. Consequences, all measured:
|
|||||||
- **Lowering `--max-model-len` is the WRONG lever and backfires:** a smaller
|
- **Lowering `--max-model-len` is the WRONG lever and backfires:** a smaller
|
||||||
context shrinks the reserve, handing the space to the arena — measured 65536
|
context shrinks the reserve, handing the space to the arena — measured 65536
|
||||||
→ 0.64 GiB KV, 32768 → 0.34 GiB KV.
|
→ 0.64 GiB KV, 32768 → 0.34 GiB KV.
|
||||||
- **Hybrid-attention undercount:** the planner's per-token KV figure (9190
|
- **Hybrid-attention undercount:** the planner's per-token KV figure for
|
||||||
B/token for Qwen4Exp) misses the large fixed per-sequence Mamba state
|
Qwen4Exp is an undercount — the printed figure and the true one are both on
|
||||||
|
[[frank-archon]] — because it misses the large fixed per-sequence Mamba state
|
||||||
(~2x), so the reserve is always short and the arena silently covers it.
|
(~2x), so the reserve is always short and the arena silently covers it.
|
||||||
Fix by pinning the pool: `--kv-cache-memory-bytes <BYTES>` (2 GiB →
|
Fix by pinning the pool: `--kv-cache-memory-bytes <BYTES>` (era reading: a
|
||||||
113,595 tokens / 3.47x concurrency at 32k). For long context,
|
2 GiB pin = 113,595 tokens ≈ 3.47x concurrency at 32k — that pair is this
|
||||||
|
page's record of the tcclaviger boots, not [[frank-archon]]'s). For long
|
||||||
|
context,
|
||||||
`--kv-offloading-size` (GiB) spills KV to host.
|
`--kv-offloading-size` (GiB) spills KV to host.
|
||||||
- **`--expert-offload-mem` caps the HOST side, not the VRAM arena**
|
- **`--expert-offload-mem` caps the HOST side, not the VRAM arena**
|
||||||
(`cap = int(x * GIB)` against `host_memory_available()`). Do not reach for
|
(`cap = int(x * GIB)` against `host_memory_available()`). Do not reach for
|
||||||
@@ -201,18 +206,21 @@ host RAM = `host-backed set + layers still loading`, not the whole model. At
|
|||||||
runtime `apply_hot_cold` sends arena-resident experts down a hot GEMM and the
|
runtime `apply_hot_cold` sends arena-resident experts down a hot GEMM and the
|
||||||
rest straight over PCIe via UVA views — no staging copy in the critical path.
|
rest straight over PCIe via UVA views — no staging copy in the critical path.
|
||||||
|
|
||||||
**Emulation check:** a dequantize-to-compute path doubles real host RAM (118
|
**Emulation check:** a dequantize-to-compute path doubles real host RAM — the
|
||||||
GiB offload request → ~238 GiB) and is invisible in the weight count. Read the
|
measured pair (offload request vs host footprint) is on [[frank-archon]] — and
|
||||||
log for `Using 'EMULATION' Mxfp4 MoE backend` before concluding "doesn't fit".
|
the doubling is invisible in the weight count. Read the log for `Using
|
||||||
|
'EMULATION' Mxfp4 MoE backend` before concluding "doesn't fit".
|
||||||
|
|
||||||
## 6. Performance profile and honest measurement
|
## 6. Performance profile and honest measurement
|
||||||
|
|
||||||
Decode on this pair is **PCIe-gather-bound, context-independent**: 12.11
|
Decode on this pair is **PCIe-gather-bound, context-independent**: the rate is
|
||||||
tok/s FLAT from 304 to 16,095 context tokens — KV attention is not the cost.
|
flat from a few hundred to sixteen thousand context tokens, so KV attention is
|
||||||
With ~29 % of experts arena-resident, ~0.84 GB crosses PCIe per token at the
|
not the cost (the flat figure and its MTP/gather deltas are
|
||||||
engine's effective read rate; cold-vs-warm differing ~10 % confirms the LRU
|
[[Tcclaviger Fork Ops]]'s profile of the same shape). With ~29 % of experts
|
||||||
works; growth is linear in hit rate, and only speculative decode cuts
|
arena-resident, under a gigabyte crosses PCIe per token at the engine's
|
||||||
sequential STEPS rather than making each cheaper.
|
effective read rate; cold-vs-warm differing ~10 % confirms the LRU works;
|
||||||
|
growth is linear in hit rate, and only speculative decode cuts sequential STEPS
|
||||||
|
rather than making each cheaper.
|
||||||
|
|
||||||
**Benchmark traps that produced fake numbers here:**
|
**Benchmark traps that produced fake numbers here:**
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,12 @@ timestamp: 2026-10-05T00:00:00-07:00
|
|||||||
|
|
||||||
# RDNA4 MoE Expert Offload VRAM Budget
|
# RDNA4 MoE Expert Offload VRAM Budget
|
||||||
|
|
||||||
For VRAM-bound vLLM on the tcclaviger RDNA4 fork (frank-archon: Qwen3.8-
|
For VRAM-bound vLLM on the tcclaviger RDNA4 fork. Every boot ledger, arena
|
||||||
Flash-Next FP8, TP=2, 2x R9700 at 31.86 GiB each, expert offload to host RAM).
|
figure and rate below is from [[frank-archon]]'s tcclaviger era (2026-09-29 →
|
||||||
Tuning history and the deployed shape live in
|
10-05: Qwen3.8-Flash-Next FP8, TP=2, 2x R9700 at 31.86 GiB each, expert offload
|
||||||
[[frank-archon]]; boot-failure capture lives in
|
to host RAM) — that page owns the endpoint's shape, tuning history and era
|
||||||
|
record; this page owns only the plan arithmetic, the ladder method and the audit
|
||||||
|
procedure. Boot-failure capture lives in
|
||||||
[[vLLM Boot Forensics and Config Interrogation]].
|
[[vLLM Boot Forensics and Config Interrogation]].
|
||||||
|
|
||||||
## 1. The plan law
|
## 1. The plan law
|
||||||
|
|||||||
@@ -7,6 +7,12 @@ timestamp: 2026-09-03
|
|||||||
---
|
---
|
||||||
|
|
||||||
# Running Qwen3.6 27B FP8 on Dankclaw
|
# Running Qwen3.6 27B FP8 on Dankclaw
|
||||||
|
> **RETIRED - vLLM era (before the 2026-08-17 redo).** Nothing on this page serves
|
||||||
|
> today: no vLLM or ROCm process runs on Dankclaw, and the iGPU endpoint at
|
||||||
|
> `192.168.0.143:7770` is [[frank-dragoon]] (halogen flash-server). The page stays as
|
||||||
|
> the era record of the Qwen3.6-27B-FP8 vLLM bring-up and the Strix Halo ROCm
|
||||||
|
> recipes ([[frank-redo-2026-08-17]]). The hardware table below carries the era's
|
||||||
|
> host figures; live ones are [[Dankclaw System Specs]].
|
||||||
|
|
||||||
## Model Information
|
## Model Information
|
||||||
|
|
||||||
@@ -29,6 +35,7 @@ Qwen3.6-27B is a dense vision-language model from the Qwen3.6 series. It uses 27
|
|||||||
| Vision Encoder | Yes (image-text-to-text) |
|
| Vision Encoder | Yes (image-text-to-text) |
|
||||||
|
|
||||||
## Hardware: Dankclaw
|
## Hardware: Dankclaw
|
||||||
|
*Era figures (2026-08). The host has changed since - [[Dankclaw System Specs]].*
|
||||||
|
|
||||||
| Property | Value |
|
| Property | Value |
|
||||||
|----------|-------|
|
|----------|-------|
|
||||||
@@ -55,7 +62,11 @@ The FP8 variant requires approximately 16-17 GB. ThinkingCap-FP8 requires ~29 GB
|
|||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
> **Production note:** Dankclaw's primary service now runs vLLM-ROCm with the Ling-3.0-flash CIRU INT4 model (see `scripts/frank-dragoon.service`). This page documents the alternative vLLM FP8 deployment of Qwen3.6-27B.
|
> **Era note (2026-08, superseded twice):** at writing time Dankclaw's primary
|
||||||
|
> service was the vLLM-ROCm Ling-3.0-flash CIRU INT4 trial ([[ling-3.0-flash-trial]],
|
||||||
|
> retired 2026-08-17), and this page documented the alternative vLLM FP8 deployment
|
||||||
|
> of Qwen3.6-27B. Both paths are dead; `scripts/frank-dragoon.service` today is the
|
||||||
|
> halogen flash-server unit ([[frank-dragoon]]).
|
||||||
|
|
||||||
Install vLLM for ROCm. Version 0.24.0+ is required for Qwen3.6 with speculative decoding:
|
Install vLLM for ROCm. Version 0.24.0+ is required for Qwen3.6 with speculative decoding:
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ In unified memory:
|
|||||||
|
|
||||||
### ROCm Version
|
### ROCm Version
|
||||||
|
|
||||||
vLLM supports AMD GPUs with ROCm 6.3 or above *(unverified 2026-10-18)*. Dankclaw has ROCm 7.2.4 from AMD repos (`/etc/apt/sources.list.d/rocm.list` → `deb https://repo.radeon.com/rocm/apt/7.2.4 noble main`; `rocm-core 7.2.4.70204-93~24.04`, read 2026-10-18). No vLLM endpoint runs on this host today — 7770 is halogen-flash-server and 7771 is llama.cpp ([[Dankclaw System Specs]]) — so this page is reference material, not the serving path.
|
vLLM supports AMD GPUs with ROCm 6.3 or above *(unverified 2026-10-18)*. Dankclaw's ROCm version and which engine owns which port today are [[Dankclaw System Specs]]'s — so this page is reference material, not the serving path.
|
||||||
|
|
||||||
Check ROCm version:
|
Check ROCm version:
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ vllm serve model \
|
|||||||
|
|
||||||
- `gpu_memory_utilization`: Set lower (0.8-0.85) to leave room for CPU operations
|
- `gpu_memory_utilization`: Set lower (0.8-0.85) to leave room for CPU operations
|
||||||
- `max_model_len`: Match actual context needs
|
- `max_model_len`: Match actual context needs
|
||||||
- The old `--swap-space` argument was removed from current vLLM — `CacheConfig` on `main` carries no `swap_space` field ([source](https://raw.githubusercontent.com/vllm-project/vllm/main/vllm/config/cache.py), read 2026-10-18). Use `--kv-offloading-size` (`kv_offloading_size`, same file) for CPU KV offload
|
- `--swap-space` is retired from current vLLM; the CPU KV-offload knob pair, with the upstream `CacheConfig` verification, is owned by [[RAM CPU Offloading in VLLM]]
|
||||||
|
|
||||||
### NUMA Binding
|
### NUMA Binding
|
||||||
|
|
||||||
@@ -166,7 +166,7 @@ Unified memory has lower bandwidth than dedicated VRAM:
|
|||||||
|
|
||||||
### ROCm Overcommit
|
### ROCm Overcommit
|
||||||
|
|
||||||
ROCm reports ~114 GiB of GPU memory on Strix Halo APU (the GTT aperture: `mem_info_gtt_total` = 122402963456 bytes = 114 GiB, read 2026-10-18 under `/sys/class/drm/card1/device/`; `llama-server --list-devices` shows 116,732 MiB — the 2026-08-17 "96 GiB" figure was stale). Physical RAM visible to the OS is **121 GiB** today (`free -g` total 121, read 2026-10-18; 64 GiB in the earlier reading on this page, upgraded from 32 GB). The GPU can address more than physical RAM exists because the GTT aperture maps over the shared LPDDR. vLLM will see ~114 GiB and try to allocate accordingly. Set `--gpu-memory-utilization` to 0.80 or lower to prevent OOM.
|
ROCm reports the GTT aperture as "GPU memory" on this APU; the aperture size, the physical `MemTotal` behind it and the firmware carve-out are [[Dankclaw System Specs]]'s numbers, and that page also carries the 2026-08-17 "96 GiB" reading this page used to quote (stale). One reporting quirk worth keeping here: `llama-server --list-devices` prints 116,732 MiB for the same device the sysfs file calls 114 GiB — engines round the aperture differently, so read the sysfs value when sizing. The GPU can address more than physical RAM exists because the GTT maps over the shared LPDDR. vLLM will see the aperture and try to allocate accordingly; set `--gpu-memory-utilization` to 0.80 or lower to prevent OOM.
|
||||||
|
|
||||||
Lower bandwidth means slower inference. Plan for lower throughput.
|
Lower bandwidth means slower inference. Plan for lower throughput.
|
||||||
|
|
||||||
@@ -232,9 +232,8 @@ FP8 quantization depends on GPU architecture:
|
|||||||
the matmul claim as the settled half.)
|
the matmul claim as the settled half.)
|
||||||
|
|
||||||
For FP4 on Dankclaw the ROCmFPX llama.cpp fork (`Q2_0_ROCMFP4`) provided native
|
For FP4 on Dankclaw the ROCmFPX llama.cpp fork (`Q2_0_ROCMFP4`) provided native
|
||||||
ROCm FP4 kernels; that runtime line is **retired** (CIRU/Kairic eras,
|
ROCm FP4 kernels; that runtime line is **retired** — the CIRU and Kairic eras on
|
||||||
[[frank-dragoon]], [[frank-dragoon]]) and no
|
[[frank-dragoon]] — and no ROCmFPX build serves this host today.
|
||||||
ROCmFPX build serves this host today.
|
|
||||||
|
|
||||||
## Example Commands
|
## Example Commands
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ TUNABLE=0`, stock gather 8×16 → 26.80/25.15/26.81 tok/s @ 166/1087/4064 ctx.
|
|||||||
|
|
||||||
Decode on this stack is PCIe-gather-bound (~30% GPU duty cycle), so
|
Decode on this stack is PCIe-gather-bound (~30% GPU duty cycle), so
|
||||||
batch-shaped compute knobs move ~nothing.
|
batch-shaped compute knobs move ~nothing.
|
||||||
|
Measured with no spec: **12.11 tok/s FLAT from 304 to 16,095 context tokens** — KV
|
||||||
|
attention is not the cost, so a context-slope hunt on this stack is null by construction.
|
||||||
|
|
||||||
The `R4D_*/CLAV_*` knob family (QSA_*, MHC, ROUTE, ACT_QUANT, AR_QUANT,
|
The `R4D_*/CLAV_*` knob family (QSA_*, MHC, ROUTE, ACT_QUANT, AR_QUANT,
|
||||||
SILU_QUANT) are kill-switches defaulting ON, not perf dials; real levers are
|
SILU_QUANT) are kill-switches defaulting ON, not perf dials; real levers are
|
||||||
@@ -120,95 +122,36 @@ exactly SEQS×(n+1) (`suboptimal` warning) → try 8192.
|
|||||||
|
|
||||||
## Serving a model larger than VRAM (dankserver recipe)
|
## Serving a model larger than VRAM (dankserver recipe)
|
||||||
|
|
||||||
Dankserver: 2× R9700 (gfx1201), 31.86 GiB each = 63.7 GiB real VRAM, 246 GiB
|
Dankserver's card count, per-card VRAM and host RAM are in [[Dankserver System Specs]];
|
||||||
RAM. `torch.cuda.device_count()` returns 3 and summing `total_memory` gives
|
`torch.cuda.device_count()` returns 3 on this box and summing `total_memory` overstates it
|
||||||
a bogus 186.7 GiB (the Raphael iGPU is in the list — see
|
badly (the Raphael iGPU is in the list — reading discipline: [[Llama Cpp Serving Sizing]]).
|
||||||
[[Llama Cpp Serving Sizing]] for the reading discipline).
|
|
||||||
|
|
||||||
**Kernel gate — this decides which checkpoint can work at all.**
|
Everything else about running this image — the quant-kernel gate that decides
|
||||||
`/app/r4dhip/r4d.so` exports `gemm_moe_mxfp4a8_*` and `gemm_moe_dsfp4a8_*`
|
which checkpoints can serve at all, the entrypoint contract, the known-good
|
||||||
but NO `gemm_moe_w4a16_*`. Expert offload requires an experts class with
|
invocation, the `/dev/dri` and memlock traps, the util and max-model-len arena
|
||||||
BOTH a compiled kernel AND an `offload_recipe`; the planner aborts startup
|
traps, the `--ipc=host` / `-d` stdout traps and the gated-fetch discipline — is
|
||||||
otherwise. Usable: MXFP4, DSFP4, FP8-HIP (`R4dMxfp4MoEExperts`,
|
written once on [[RDNA4 Container Serving]], and the plan arithmetic behind the
|
||||||
`R4dDsfp4MoEExperts`, `Fp8HipMoEExperts`). `R4dW4a16MoEExperts` has no
|
arena/KV traps is [[RDNA4 MoE Expert Offload VRAM Budget]]'s. Three findings
|
||||||
kernel (the class exists, the r4d.so entry does not); RFA has neither. Check
|
stay here because this harness produced them:
|
||||||
the checkpoint's quant against this list BEFORE downloading anything.
|
|
||||||
|
|
||||||
Entrypoint is `/app/tools/image_entrypoint.sh`, ending `exec vllm serve
|
- **The KV reserve undercounts hybrid-attention models ~2×** (the planner's
|
||||||
"$@"` — pass the model path as the FIRST argument and do NOT pass `serve`.
|
B/token figure against ~18,000 real: the Mamba state is a fixed per-sequence
|
||||||
Known-good invocation:
|
cost). Fix by pinning the pool: `--kv-cache-memory-bytes`.
|
||||||
|
- **`--expert-offload-mem` caps the HOST side**, not the VRAM arena —
|
||||||
|
structurally orthogonal to `--expert-precise-memory` (verified in-container
|
||||||
|
2026-10-05: precise-memory only swaps the GPU overhead term,
|
||||||
|
expert_offload_mem only sets the host bound; they rejoin only inside
|
||||||
|
`place_experts`, and the plan rewrites `expert_offload_mem` back to the cap
|
||||||
|
the plan met, so plan and allocation cannot drift).
|
||||||
|
- **Check whether the stack supports the model natively before porting an
|
||||||
|
overlay.** The image already registered `Glm5NextForConditionalGeneration`,
|
||||||
|
`Qwen4ExpForCausalLM` and both MTP variants — chasing four missing symbols
|
||||||
|
through two image tags to bring an overlay up was entirely wasted work.
|
||||||
|
|
||||||
```bash
|
The checkpoint this recipe was verified on is
|
||||||
sudo sh -c 'sync; echo 3 > /proc/sys/vm/drop_caches'
|
`orcarouter/Qwen3.8-Flash-Next-Uncensored-FP8` (gated; 172.8 GiB, 131 shards,
|
||||||
podman run -d --name <ctr> --ipc=host --ulimit memlock=-1:-1 \
|
`Qwen4ExpForConditionalGeneration`, 48 layers, 512 experts top-10, multimodal,
|
||||||
--cap-add SYS_PTRACE \
|
native 262,144) — an [[frank-archon]] era payload.
|
||||||
--device /dev/kfd --device /dev/dri --device /dev/mem \
|
|
||||||
-e HIP_VISIBLE_DEVICES=0,1 -e VLLM_ROCM_USE_AITER=0 \
|
|
||||||
-v /home/dank/models/<model>:/models:ro \
|
|
||||||
docker.io/tcclaviger/vllm:latest /models \
|
|
||||||
--served-model-name <name> --port 7770 \
|
|
||||||
--tensor-parallel-size 2 \
|
|
||||||
--max-model-len 32768 \
|
|
||||||
--kv-cache-memory-bytes 2147483648 \
|
|
||||||
--max-num-seqs 4 \
|
|
||||||
--gpu-memory-utilization 0.95 \
|
|
||||||
--enable-prefix-caching --trust-remote-code
|
|
||||||
```
|
|
||||||
|
|
||||||
`-p 7770:7770` is not included, so the API is only reachable via
|
|
||||||
`podman exec` — add `-p` if host-side curl is needed. Load ~5 min;
|
|
||||||
`/health` answers connection-refused the whole time; watch for
|
|
||||||
`Application startup complete` in `podman logs <ctr>`. Verified working:
|
|
||||||
`orcarouter/Qwen3.8-Flash-Next-Uncensored-FP8` (gated; 172.8 GiB, 131
|
|
||||||
shards, `Qwen4ExpForConditionalGeneration`, 48 layers, 512 experts top-10,
|
|
||||||
multimodal, native 262,144).
|
|
||||||
|
|
||||||
Traps that each cost a boot:
|
|
||||||
|
|
||||||
1. **Mount the whole `/dev/dri`, never individual render nodes.** Render
|
|
||||||
nodes without the primary `card*` nodes → HIP enumerates two agents and
|
|
||||||
refuses a context on either (`RuntimeError: No CUDA GPUs are available`)
|
|
||||||
while `device_count()` cheerfully returns 2. Confirmed by direct A/B.
|
|
||||||
2. **memlock must be raised** (done on Dankserver via
|
|
||||||
`/etc/security/limits.d/99-memlock.conf`). Host default 8 MiB makes any
|
|
||||||
large pinned allocation fail as a misleading
|
|
||||||
`torch.AcceleratorError: CUDA error: out of memory` from `pin_memory()`;
|
|
||||||
it cannot be raised from inside a container or root's own shell — only
|
|
||||||
PAM applies it at login. Matters because `--expert-host-mlock` defaults
|
|
||||||
True.
|
|
||||||
3. **`--gpu-memory-utilization` does NOT buy KV under expert offload** —
|
|
||||||
the planner sizes the arena against the budget and leaves KV the
|
|
||||||
remainder; raising util 0.95→0.98 grew the arena and the KV pool stayed
|
|
||||||
at 0.64 GiB.
|
|
||||||
4. **Lowering `--max-model-len` is the WRONG lever and backfires** — the
|
|
||||||
budget subtracts the KV reserve first, so a smaller context shrinks the
|
|
||||||
reserve and hands the space to the arena (measured: 65536 → 0.64 GiB KV;
|
|
||||||
32768 → 0.34 GiB).
|
|
||||||
5. **The KV reserve undercounts hybrid-attention models ~2×** (9190 B/token
|
|
||||||
planned vs ~18,000 real: the Mamba state is a fixed per-sequence cost).
|
|
||||||
Fix by pinning the pool: `--kv-cache-memory-bytes`.
|
|
||||||
6. **`--expert-offload-mem` caps the HOST side**, not the VRAM arena —
|
|
||||||
structurally orthogonal to `--expert-precise-memory` (verified
|
|
||||||
in-container 2026-10-05: precise-memory only swaps the GPU overhead term,
|
|
||||||
expert_offload_mem only sets the host bound; they rejoin only inside
|
|
||||||
`place_experts`, and the plan rewrites `expert_offload_mem` back to the
|
|
||||||
cap the plan met, so plan and allocation cannot drift).
|
|
||||||
7. `--ipc=host` and `--shm-size` are mutually exclusive in podman; pick one.
|
|
||||||
8. `podman run -d` without `-a` sends no stdout to a redirect — the log file
|
|
||||||
only receives the container ID; use `podman logs`.
|
|
||||||
|
|
||||||
Status reads: use `scripts/dankstatus.sh`, never hand-rolled
|
|
||||||
`/proc/meminfo` parsing — `/proc/meminfo` separates key from value with a
|
|
||||||
TAB, so `grep MemAvailable | tr -s " " | cut -d" " -f2` returns empty and
|
|
||||||
awk prints `0.0` — a false "host out of memory" that invites an unnecessary
|
|
||||||
abort. Gated checkpoints: token via a mode-600 `curl -K` config, never argv
|
|
||||||
(`pgrep -a curl` prints it); always `--fail`; compare each file's byte count
|
|
||||||
to the Hub's declared size; `-C -` resumes truncated shards.
|
|
||||||
|
|
||||||
**Check whether the stack supports the model natively before porting an
|
|
||||||
overlay.** The image already registered `Glm5NextForConditionalGeneration`,
|
|
||||||
`Qwen4ExpForCausalLM` and both MTP variants — chasing four missing symbols
|
|
||||||
through two image tags to bring an overlay up was entirely wasted work.
|
|
||||||
|
|
||||||
## Compile-cache persistence (survives `podman rm -f`)
|
## Compile-cache persistence (survives `podman rm -f`)
|
||||||
|
|
||||||
@@ -240,20 +183,15 @@ cold, of which 173 s was one graph).
|
|||||||
|
|
||||||
## Plan-line verification checklist (after any fork deploy)
|
## Plan-line verification checklist (after any fork deploy)
|
||||||
|
|
||||||
```
|
The journal one-liner that reads the plan lines (digit-anchored `grep -oE`,
|
||||||
ssh dankserver 'sudo journalctl CONTAINER_NAME=frank-archon-qwen -b -o cat --no-pager \
|
because plain grep truncates those columns to `17.`) and the post-deploy
|
||||||
| grep -aoE "(budget \(total x util\) +[0-9.]+|expert cache space +[0-9.]+ GiB +[0-9,]+ slots|Estimated CUDA graph memory.{0,80}|Graph capturing finished.{0,40}|GPU KV cache size.{0,90})"'
|
verification order — plan vs captured graph memory, `GPU KV cache size` vs the
|
||||||
```
|
ask, per-card `rocm-smi` high-water, `NRestarts` = 0, `VLLM_CUDAGRAPH_*` present
|
||||||
|
in the container env, then a real completion from a PEER because
|
||||||
`grep -oE` with a digit-anchored tail — plain `grep`/journalctl truncate
|
`curl localhost:7770/health` inside an ssh session on the host can return `000`
|
||||||
these columns to `17.`. Verify: new budget/graphs/arena in the plan;
|
and look like an outage — are step 3 of
|
||||||
`GPU KV cache size` matches the requested token count; `Estimated CUDA graph
|
[[RDNA4 MoE Expert Offload VRAM Budget]] §7. Run that; do not re-derive it
|
||||||
memory` vs the capture line (raise `_PER_GRAPH_MB` toward 52 if capture
|
here.
|
||||||
exceeds the charge); `rocm-smi --showmeminfo vram` high-water per card = the
|
|
||||||
real margin; `systemctl show frank-archon -p NRestarts --value` = 0;
|
|
||||||
`VLLM_CUDAGRAPH_*` present in `podman exec … env`; then a real chat
|
|
||||||
completion from a PEER — `curl localhost:7770/health` inside an ssh session
|
|
||||||
on the host can return `000` and looks like an outage that isn't.
|
|
||||||
|
|
||||||
## Related
|
## Related
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ vllm serve meta-llama/Llama-3.1-70B-Instruct --tensor-parallel-size 4
|
|||||||
vllm serve Qwen/Qwen2.5-1.5B-Instruct --quantization fp8
|
vllm serve Qwen/Qwen2.5-1.5B-Instruct --quantization fp8
|
||||||
|
|
||||||
# With GPU memory control
|
# With GPU memory control
|
||||||
vllm serve Qwen/Qwen2.5-1.5B-Instruct --gpu-memory-utilization 0.8 --swap-space 8
|
vllm serve Qwen/Qwen2.5-1.5B-Instruct --gpu-memory-utilization 0.8 --kv-offloading-size 8 --kv-offloading-backend native
|
||||||
```
|
```
|
||||||
|
|
||||||
### Common API Endpoints
|
### Common API Endpoints
|
||||||
@@ -79,7 +79,7 @@ vllm serve Qwen/Qwen2.5-1.5B-Instruct --gpu-memory-utilization 0.8 --swap-space
|
|||||||
|-----------|-------------|---------------|
|
|-----------|-------------|---------------|
|
||||||
| tensor_parallel_size | Number of GPUs for model sharding | 1-8 |
|
| tensor_parallel_size | Number of GPUs for model sharding | 1-8 |
|
||||||
| gpu_memory_utilization | Fraction of GPU memory for KV cache (default 0.92) | 0.7-0.95 |
|
| gpu_memory_utilization | Fraction of GPU memory for KV cache (default 0.92) | 0.7-0.95 |
|
||||||
| swap_space | Removed in current vLLM; use `--kv-offloading-size` | n/a |
|
| swap_space | Retired; live knob pair in [[RAM CPU Offloading in VLLM]] | n/a |
|
||||||
| max_model_len | Maximum context length | auto |
|
| max_model_len | Maximum context length | auto |
|
||||||
| max_num_batched_tokens | Max tokens per batch | 2048-8192 |
|
| max_num_batched_tokens | Max tokens per batch | 2048-8192 |
|
||||||
| max_num_seqs | Max sequences per batch | 128-512 |
|
| max_num_seqs | Max sequences per batch | 128-512 |
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ curl http://localhost:8000/v1/chat/completions \
|
|||||||
| `tensor_parallel_size` | 1 | Number of GPUs for tensor parallelism |
|
| `tensor_parallel_size` | 1 | Number of GPUs for tensor parallelism |
|
||||||
| `pipeline_parallel_size` | 1 | Number of GPUs for pipeline parallelism |
|
| `pipeline_parallel_size` | 1 | Number of GPUs for pipeline parallelism |
|
||||||
| `gpu_memory_utilization` | 0.92 | Fraction of GPU memory for KV cache |
|
| `gpu_memory_utilization` | 0.92 | Fraction of GPU memory for KV cache |
|
||||||
| `swap_space` | removed | Removed in current vLLM; use `--kv-offloading-size` |
|
| `swap_space` | — | retired; the live CPU-KV-offload knob pair is in [[RAM CPU Offloading in VLLM]] |
|
||||||
| `enforce_eager` | false | Use eager mode (no CUDA graphs) |
|
| `enforce_eager` | false | Use eager mode (no CUDA graphs) |
|
||||||
| `max_num_batched_tokens` | 2048 | Max tokens per batch |
|
| `max_num_batched_tokens` | 2048 | Max tokens per batch |
|
||||||
| `max_num_seqs` | 128 | Max sequences per batch |
|
| `max_num_seqs` | 128 | Max sequences per batch |
|
||||||
@@ -167,7 +167,7 @@ curl http://localhost:8000/v1/chat/completions \
|
|||||||
| Argument | Default | Description |
|
| Argument | Default | Description |
|
||||||
|----------|---------|-------------|
|
|----------|---------|-------------|
|
||||||
| `gpu_memory_utilization` | 0.92 | Fraction of GPU memory for KV cache |
|
| `gpu_memory_utilization` | 0.92 | Fraction of GPU memory for KV cache |
|
||||||
| `swap_space` | removed | Removed in current vLLM; use `--kv-offloading-size` |
|
| `swap_space` | — | retired; the live CPU-KV-offload knob pair is in [[RAM CPU Offloading in VLLM]] |
|
||||||
| `kv_cache_dtype` | auto | KV cache data type (auto, fp8, fp8_e5m2) |
|
| `kv_cache_dtype` | auto | KV cache data type (auto, fp8, fp8_e5m2) |
|
||||||
| `max_model_len` | auto | Maximum context length |
|
| `max_model_len` | auto | Maximum context length |
|
||||||
| `num_gpu_blocks` | auto | Number of GPU blocks |
|
| `num_gpu_blocks` | auto | Number of GPU blocks |
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ timestamp: 2026-09-03
|
|||||||
|
|
||||||
> **SUPERSEDED 2026-08-17.** The Frank redo retired this topology.
|
> **SUPERSEDED 2026-08-17.** The Frank redo retired this topology.
|
||||||
> See [[frank-redo-2026-08-17]] and [[deployment]] for the active configuration.
|
> See [[frank-redo-2026-08-17]] and [[deployment]] for the active configuration.
|
||||||
|
> The `frank-zealot` below is the 2026-08 service: llama.cpp on the RTX 3090
|
||||||
|
> **while that card sat in Dankserver**. Today's [[frank-zealot]] is a different host
|
||||||
|
> (Dankclaw), payload and runtime build, though the same card class - this crash
|
||||||
|
> signature is not a live fault.
|
||||||
|
|
||||||
# Dankserver VRAM and RAM Growth Under Load
|
# Dankserver VRAM and RAM Growth Under Load
|
||||||
|
|
||||||
|
|||||||
@@ -241,6 +241,11 @@ Before 2026-09-26 the port belonged to the **`frank-medium`** service: [[frank-m
|
|||||||
seqs 2 and seqs 3 are statistically tied (30.9-33.1 t/s, inside the ±3 % floor). The "seqs 2
|
seqs 2 and seqs 3 are statistically tied (30.9-33.1 t/s, inside the ±3 % floor). The "seqs 2
|
||||||
cannot boot" law belonged to the retired tcclaviger fork's `torch.compile` shape
|
cannot boot" law belonged to the retired tcclaviger fork's `torch.compile` shape
|
||||||
specialization, and radiance booted seqs 2 on its first fp8-native start.
|
specialization, and radiance booted seqs 2 on its first fp8-native start.
|
||||||
|
**Same era, separate law: a dequantize-to-compute path bills host RAM twice.** On the
|
||||||
|
EMULATION backend an offload request of **118 GiB** landed as **~238 GiB** of real host RAM —
|
||||||
|
the dequantized copy rides on top of the pinned weights, and the doubling is invisible in the
|
||||||
|
weight count. Read the engine log for `Using 'EMULATION' Mxfp4 MoE backend` before concluding
|
||||||
|
"doesn't fit"; the container-side procedure and the kernel gate are [[RDNA4 Container Serving]].
|
||||||
- **One encoding per expert table** (`rad_arch_declare`): a whole expert kept bf16 is the only
|
- **One encoding per expert table** (`rad_arch_declare`): a whole expert kept bf16 is the only
|
||||||
thing legal beside the table, so a split tier (down=fp8, gate_up=w4) is unservable.
|
thing legal beside the table, so a split tier (down=fp8, gate_up=w4) is unservable.
|
||||||
- **Descriptor-selection law.** The plugin is picked by the exact `(arch_id, quant descriptor)`
|
- **Descriptor-selection law.** The plugin is picked by the exact `(arch_id, quant descriptor)`
|
||||||
|
|||||||
@@ -25,6 +25,12 @@ what each buys. The answer is that `--ubatch-size` has an **optimum** on this
|
|||||||
stack, that the logical batch does not matter at all, and that the optimum is
|
stack, that the logical batch does not matter at all, and that the optimum is
|
||||||
much cheaper than what was deployed — which then moved the layer split.
|
much cheaper than what was deployed — which then moved the layer split.
|
||||||
|
|
||||||
|
The deployment this sweep tuned (`frank-medium`, 2x R9700, llama.cpp layer
|
||||||
|
split) is retired; its shape and boot ledger are
|
||||||
|
[[frank-medium-llamacpp-dflash2]]'s, and the endpoint lineage continues on
|
||||||
|
[[frank-archon]]. What this page owns is the sweep, the harness traps and the
|
||||||
|
coupling law between batch and split.
|
||||||
|
|
||||||
## The shape of the measurement
|
## The shape of the measurement
|
||||||
|
|
||||||
A cell is a **64k prefill measured with 64k of KV already resident**, plus a
|
A cell is a **64k prefill measured with 64k of KV already resident**, plus a
|
||||||
@@ -104,7 +110,7 @@ kill — no requests):
|
|||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| 36,29 — deployed before | 1536 | 4.71 GiB | 4.91 GiB | 0.20 GiB |
|
| 36,29 — deployed before | 1536 | 4.71 GiB | 4.91 GiB | 0.20 GiB |
|
||||||
| 36,29 | **512** | 6.01 GiB | 7.32 GiB | 1.31 GiB |
|
| 36,29 | **512** | 6.01 GiB | 7.32 GiB | 1.31 GiB |
|
||||||
| **35,30 — deployed now** | **512** | **6.44 GiB** | **6.90 GiB** | **0.46 GiB** |
|
| **35,30 — deployed after** | **512** | **6.44 GiB** | **6.90 GiB** | **0.46 GiB** |
|
||||||
|
|
||||||
Two things follow.
|
Two things follow.
|
||||||
|
|
||||||
@@ -153,7 +159,7 @@ other (measured 2.41 GiB vs 1.30 GiB going 1536 → 512). Balance by
|
|||||||
measurement only: one `-ts` step is one layer, worth ~0.43 GiB on a DeltaNet
|
measurement only: one `-ts` step is one layer, worth ~0.43 GiB on a DeltaNet
|
||||||
boundary and ~1.43 GiB on an attention one, so the reachable minimum gap is
|
boundary and ~1.43 GiB on an attention one, so the reachable minimum gap is
|
||||||
about one DeltaNet layer, never zero. Reference: 36,29 @1536 → 4.71/4.91;
|
about one DeltaNet layer, never zero. Reference: 36,29 @1536 → 4.71/4.91;
|
||||||
36,29 @512 → 6.01/7.32; **35,30 @512 → 6.44/6.90 (deployed)**.
|
36,29 @512 → 6.01/7.32; **35,30 @512 → 6.44/6.90 (the shape that deployed)**.
|
||||||
|
|
||||||
Re-fit both ubatch coefficients in `tests/frank_medium_unit.bats` at the new
|
Re-fit both ubatch coefficients in `tests/frank_medium_unit.bats` at the new
|
||||||
deployed point and re-anchor the per-card constants; check neighbouring
|
deployed point and re-anchor the per-card constants; check neighbouring
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
type: runbook
|
type: runbook
|
||||||
title: frank-medium Model Swap
|
title: frank-medium Model Swap
|
||||||
description: How to swap the checkpoint behind the frank-medium endpoint (Dankserver :7770, vllm-radiance TP=2) — the streamlining toolchain (hf-manifest.py, hf-fetch.sh, swap-frank-medium.sh), the quantization-aware entrypoint contract, the quadlet edit, the deploy, the capability battery, and the rollback path.
|
description: RETIRED-era procedure (frank-medium is a retired endpoint; `:7770` on Dankserver is [[frank-archon]] today and the live swap law is [[Model Swap and Rollback]]) — how a checkpoint swap behind frank-medium worked: the streamlining toolchain (hf-manifest.py, hf-fetch.sh, swap-frank-medium.sh), the quantization-aware entrypoint contract, the quadlet edit, the deploy, the capability battery, and the rollback path.
|
||||||
tags:
|
tags:
|
||||||
- frank-medium
|
- frank-medium
|
||||||
- dankserver
|
- dankserver
|
||||||
@@ -14,12 +14,13 @@ timestamp: 2026-09-20
|
|||||||
|
|
||||||
# frank-medium Model Swap
|
# frank-medium Model Swap
|
||||||
|
|
||||||
Swapping the checkpoint behind **frank-medium** (Dankserver `:7770`,
|
**Historical.** frank-medium is a retired endpoint — `:7770` on Dankserver is
|
||||||
vllm-radiance TP=2) is a four-step process, and the toolchain below drives all
|
[[frank-archon]] today, and the live procedure is [[Model Swap and Rollback]].
|
||||||
of it. The design goal (2026-09-20, after the MXFP4 → FP8 swap) is that a swap
|
This page records how a swap worked in that era: a four-step process whose design
|
||||||
is **one command**: generate a manifest, download it verified, point the
|
goal (2026-09-20, after the MXFP4 → FP8 swap) was that a swap be **one command** —
|
||||||
quadlet at it, deploy. The entrypoint is quantization-aware, so the only repo
|
generate a manifest, download it verified, point the quadlet at it, deploy. The
|
||||||
change a swap makes is the quadlet's four env vars.
|
entrypoint was quantization-aware, so the only repo change a swap made was the
|
||||||
|
quadlet's four env vars.
|
||||||
|
|
||||||
## Why this exists
|
## Why this exists
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
type: configuration
|
type: configuration
|
||||||
title: frank-medium vllm-radiance MXFP6 Runbook
|
title: frank-medium vllm-radiance MXFP6 Runbook
|
||||||
description: ACTIVE frank-medium runbook — vllm-radiance serving hugypufy/Swift-Qwen3.8-27B-PARO-MXFP6 (ParoQuant MXFP6 W4A8, DFlash2 drafter, unquantized bf16 KV) as ONE tensor-parallel process (TP=2) on Dankserver's two AMD Radeon AI PRO R9700 (gfx1201). Cut to MXFP6 on 2026-09-21 (PR #51's launch6_p kernel, image 0.13.0-e060895); the MXFP4 checkpoint (just1moremodel/Qwen3.8-27B-Uncensored-MXFP4-awq, the 2026-09-21 shape) is the on-disk rollback. Model-swap process: [[frank-medium-model-swap]]. The sections below describe the 2026-09-16 two-replica era.
|
description: RETIRED era runbook (endpoint renamed frank-archon 2026-10-10; this shape is a row in [[frank-archon]]'s Eras table) — vllm-radiance serving hugypufy/Swift-Qwen3.8-27B-PARO-MXFP6 (ParoQuant MXFP6 W4A8, DFlash2 drafter, unquantized bf16 KV) as ONE tensor-parallel process (TP=2) on Dankserver's two AMD Radeon AI PRO R9700 (gfx1201). Cut to MXFP6 on 2026-09-21 (PR #51's launch6_p kernel, image 0.13.0-e060895); the MXFP4 checkpoint (just1moremodel/Qwen3.8-27B-Uncensored-MXFP4-awq, the 2026-09-21 shape) is the on-disk rollback. Model-swap process: [[frank-medium-model-swap]]. The sections below describe the 2026-09-16 two-replica era.
|
||||||
tags:
|
tags:
|
||||||
- frank-medium
|
- frank-medium
|
||||||
- dankserver
|
- dankserver
|
||||||
@@ -19,7 +19,8 @@ timestamp: 2026-09-21
|
|||||||
|
|
||||||
# frank-medium vllm-radiance MXFP6 Runbook
|
# frank-medium vllm-radiance MXFP6 Runbook
|
||||||
|
|
||||||
The ACTIVE frank-medium deployment: the `ggz14/vllm-radiance-mxfp4:0.13.0-e060895`
|
**RETIRED era (2026-09-21 → 10-10; the endpoint is [[frank-archon]] today and this
|
||||||
|
shape is one row in its Eras table.)** The deployment was the `ggz14/vllm-radiance-mxfp4:0.13.0-e060895`
|
||||||
image (built from PR #51's head, tagged locally as
|
image (built from PR #51's head, tagged locally as
|
||||||
`localhost/radiance-vllm:0.13.0-e060895`) plus the `radiance-vllm-mxfp4`
|
`localhost/radiance-vllm:0.13.0-e060895`) plus the `radiance-vllm-mxfp4`
|
||||||
patches at e060895, serving `hugypufy/Swift-Qwen3.8-27B-PARO-MXFP6`
|
patches at e060895, serving `hugypufy/Swift-Qwen3.8-27B-PARO-MXFP6`
|
||||||
|
|||||||
@@ -14,14 +14,10 @@ The pipeline-parallel split and the FastFlowLM NPU endpoint were retired.
|
|||||||
The old scripts moved to `old/scripts/` in this repository.
|
The old scripts moved to `old/scripts/` in this repository.
|
||||||
|
|
||||||
> **HISTORY — the topology below is two fleet generations dead.** Today the
|
> **HISTORY — the topology below is two fleet generations dead.** Today the
|
||||||
> fleet is three endpoints: [[frank-archon]]
|
> fleet is three endpoints, each owned by its page: [[frank-archon]]
|
||||||
> (`192.168.0.235:7770`, radiance 1.0.13, 2×R9700 TP=2),
|
> (`192.168.0.235:7770`), [[frank-dragoon]] (`192.168.0.143:7770`) and
|
||||||
> [[frank-dragoon]] (`192.168.0.143:7770`, halogen
|
> [[frank-zealot]] (`192.168.0.143:7771`). No vLLM and no ROCm endpoint serves
|
||||||
> flash-server 0.16.2 on the iGPU) and
|
> anything; there is no pipeline parallelism and no NPU endpoint.
|
||||||
> [[frank-zealot]] (`192.168.0.143:7771`, llama.cpp
|
|
||||||
> PrismML fork build 10754 on the RTX 3090 — the card that sat in Dankserver
|
|
||||||
> until 2026-09-15). No vLLM and no ROCm endpoint serves anything; there is no
|
|
||||||
> pipeline parallelism and no NPU endpoint.
|
|
||||||
|
|
||||||
## New Topology
|
## New Topology
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ each of those owns exactly that one thing. The incidents behind the laws are in
|
|||||||
|---|---|
|
|---|---|
|
||||||
| [[frank-medium-batch-ubatch]] | llama-bench sweep of --batch-size against --ubatch-size on frank-medium (2x Radeon AI PRO R9700, layer split) at the… |
|
| [[frank-medium-batch-ubatch]] | llama-bench sweep of --batch-size against --ubatch-size on frank-medium (2x Radeon AI PRO R9700, layer split) at the… |
|
||||||
| [[frank-medium-llamacpp-dflash2]] | The former ACTIVE frank-medium deployment since 2026-09-16 (model swapped 2026-09-19) — mainline llama.cpp on… |
|
| [[frank-medium-llamacpp-dflash2]] | The former ACTIVE frank-medium deployment since 2026-09-16 (model swapped 2026-09-19) — mainline llama.cpp on… |
|
||||||
| [[frank-medium-model-swap]] | How to swap the checkpoint behind the frank-medium endpoint (Dankserver :7770, vllm-radiance TP=2) — the streamlining… |
|
| [[frank-medium-model-swap]] | RETIRED-era swap procedure for the frank-medium endpoint (`:7770` is now [[frank-archon]]) — the… |
|
||||||
| [[frank-medium-radiance-mxfp4]] | ACTIVE frank-medium runbook — vllm-radiance serving hugypufy/Swift-Qwen3.8-27B-PARO-MXFP6 (ParoQuant MXFP6 W4A8,… |
|
| [[frank-medium-radiance-mxfp4]] | RETIRED frank-medium era runbook — vllm-radiance serving hugypufy/Swift-Qwen3.8-27B-PARO-MXFP6 (ParoQuant MXFP6 W4A8,… |
|
||||||
| [[frank-medium-rocmfpx]] | charlie12345/ROCmFPX llama.cpp serving kingjones777/Qwen3.8-27B-ROCmFPX-Q8_0-AGENT-GGUF as frank-medium on Dankserver… |
|
| [[frank-medium-rocmfpx]] | charlie12345/ROCmFPX llama.cpp serving kingjones777/Qwen3.8-27B-ROCmFPX-Q8_0-AGENT-GGUF as frank-medium on Dankserver… |
|
||||||
| [[frank-npu]] | The retired FastFlowLM endpoint on Dankclaw's XDNA2 NPU — what it served, why it died on 2026-09-11 with the… |
|
| [[frank-npu]] | The retired FastFlowLM endpoint on Dankclaw's XDNA2 NPU — what it served, why it died on 2026-09-11 with the… |
|
||||||
| [[frank-redo-2026-08-17]] | This page records the full redo of the inference fleet on 2026-08-17. |
|
| [[frank-redo-2026-08-17]] | This page records the full redo of the inference fleet on 2026-08-17. |
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ This page was the plan for a vLLM-ROCm deployment of
|
|||||||
Dankclaw. The deployment never shipped. The actual Ling work used the
|
Dankclaw. The deployment never shipped. The actual Ling work used the
|
||||||
llama.cpp Q6_K fork trial instead: [[ling-3.0-flash-trial]].
|
llama.cpp Q6_K fork trial instead: [[ling-3.0-flash-trial]].
|
||||||
|
|
||||||
The trial service (`frank-dragoon-ling`) is retired and disabled under the
|
The trial service (`frank-dragoon-ling`) was retired and disabled under the boot
|
||||||
boot policy (2026-08-17). `frank-dragoon` is the Qwen3.8-27B PP
|
policy on 2026-08-17, in the same redo that renamed `frank-dragoon` to the
|
||||||
head, not the Ling path. See git history for the full decision table.
|
Qwen3.8-27B PP head ([[frank-redo-2026-08-17]]). Two fleet generations later the
|
||||||
|
name belongs to the halogen flash-server endpoint ([[frank-dragoon]]). See git
|
||||||
|
history for the full decision table.
|
||||||
|
|||||||
@@ -14,54 +14,28 @@ timestamp: 2026-09-03
|
|||||||
# Qwen3.8-27B Speculative-Decoding Matrix
|
# Qwen3.8-27B Speculative-Decoding Matrix
|
||||||
|
|
||||||
This page records the speculative-decoding benchmark history and the
|
This page records the speculative-decoding benchmark history and the
|
||||||
production tuning for the Qwen3.8-27B service (`frank-dragoon`),
|
production tuning for the then-Qwen3.8-27B service (`frank-dragoon`), at the
|
||||||
now a pipeline-parallel head with a Dankserver worker.
|
time a pipeline-parallel head with a Dankserver worker.
|
||||||
|
|
||||||
## Production state (2026-08-17: Q6_K, q8_0/f16 KV, split 0.68)
|
## Production state (2026-08-17)
|
||||||
|
|
||||||
Current production, verified against the live process and journal
|
The pipeline-parallel shape this matrix was tuned for — Q6_K target, standalone
|
||||||
(2026-08-17, load 02:06 + smoke tests). Topology detail:
|
Q8_0 draft on ROCm0 only, `--tensor-split 0.68,0.32` (45 of 65 blocks), K `q8_0`
|
||||||
[[Pipeline Parallelism/Qwen3.8 PP Deployment]].
|
/ V `f16`, pool 262144 at one slot, worker steady at 23854/24576 MiB — is
|
||||||
|
recorded once, in [[Pipeline Parallelism/Qwen3.8 PP Deployment]] §Production
|
||||||
- Devices: `RPC0` (Dankserver RTX 3090) + `ROCm0` (Strix iGPU). The head
|
state, together with the split-limit arithmetic (why 45 blocks is the maximum),
|
||||||
passes no `--device` flag. Default selection puts RPC first and picks
|
the KV-per-layer bill and the FA-all-quants rebuild the mismatch needed. That
|
||||||
ROCm for the iGPU (HIP registers before Vulkan). The Vulkan0 side stays
|
era's endpoint identity is an [[frank-dragoon]] era. This page keeps only the
|
||||||
an option via `HEAD_BIN=.../build-vulkan-rpc`.
|
speculative-decoding measurements.
|
||||||
- Model: `Qwen3.8-27B-Uncensored-Q6_K.gguf` (JonathanColetti, 22.43 GB,
|
|
||||||
imatrix, 65 blocks, 866 tensors, NO bundled MTP head). The repo's
|
|
||||||
standalone draft sidecar `Qwen3.8-27B-Uncensored-draft-Q8_0.gguf`
|
|
||||||
(3.16 GB) is loaded via `--spec-draft-model`; it runs on ROCm0 only
|
|
||||||
(1718 MiB, zero worker impact).
|
|
||||||
- Spec: **MTP** (standalone draft) `--spec-draft-n-max 4` + the
|
|
||||||
`--spec-default` ngram-mod fallback (48/64/24). Measured acceptance
|
|
||||||
0.83 then 0.75, mean len 4.0-4.3, per-position ~0.86/0.71/0.71/0.71 —
|
|
||||||
stronger than the old bundled head (0.739/0.554/0.427/0.340).
|
|
||||||
- KV: K **q8_0** + V **f16** (mismatched). 3136 B/token per FA layer =
|
|
||||||
784 MiB at 262144 (K 1088 + V 2048). RPC0 8624 MiB (11 FA), ROCm0
|
|
||||||
3920 MiB (5 FA); total 12544 = 16 x 784. **Flash Attention stays
|
|
||||||
enabled with the mismatch** (`resolve_fused_ops: Flash Attention
|
|
||||||
enabled`) via the GGML_CUDA_FA_ALL_QUANTS rebuild of both binaries
|
|
||||||
at 9b05354ec — see the PP doc.
|
|
||||||
- Split: `--tensor-split 0.68,0.32` = 45 of 65 blocks (0-44) on the
|
|
||||||
3090, 69% of the layer weight. The maximum: 46 blocks -> ~0.3 GiB
|
|
||||||
margin; 48 blocks (f >= 0.7197) adds FA block 47 -> KV 9408 -> OOM by
|
|
||||||
~0.85 GiB. Boundary math: the PP doc.
|
|
||||||
- Context: pool 262144, 1 slot, `n_ctx_slot = 262144`. The pi
|
|
||||||
`models.json` declares 262144 (contextWindow = maxTokens, house
|
|
||||||
convention).
|
|
||||||
- Worker steady state: 23854/24576 MiB used on the 3090, ~273 MiB free
|
|
||||||
(tight but stable; all allocations happen at load).
|
|
||||||
- Batch 8192 / ubatch 256, `--direct-io`, `--fit off`,
|
|
||||||
`--gpu-layers all`.
|
|
||||||
|
|
||||||
## How MTP works on Qwen3.8 (bundled-head era)
|
## How MTP works on Qwen3.8 (bundled-head era)
|
||||||
|
|
||||||
The unsloth `UD-*` GGUFs keep the MTP (Multi-Token Prediction) head inside
|
The unsloth `UD-*` GGUFs keep the MTP (Multi-Token Prediction) head inside
|
||||||
the model file. llama.cpp b10411+ auto-detects it and creates the draft
|
the model file. llama.cpp b10411+ auto-detects it and creates the draft
|
||||||
context from the target model. Do not pass `--spec-draft-model` for those
|
context from the target model. Do not pass `--spec-draft-model` for those
|
||||||
files. This is superseded: the production `Qwen3.8-27B-Uncensored-Q6_K.gguf`
|
files. This is superseded: the production target of 2026-08-17 carried no
|
||||||
has NO bundled head, and the serve script passes the standalone draft
|
bundled head, and the serve script passed the standalone draft sidecar with
|
||||||
sidecar with `--spec-draft-model` (see Production state above).
|
`--spec-draft-model` (shape: [[Pipeline Parallelism/Qwen3.8 PP Deployment]]).
|
||||||
|
|
||||||
The stock llama.cpp build must be b10411 or newer. The 2026-08-14 rebuild
|
The stock llama.cpp build must be b10411 or newer. The 2026-08-14 rebuild
|
||||||
on Dankclaw is b10433 (`9b05354ec`) with `GGML_HIP` + `gfx1151` + Vulkan.
|
on Dankclaw is b10433 (`9b05354ec`) with `GGML_HIP` + `gfx1151` + Vulkan.
|
||||||
@@ -83,14 +57,14 @@ standalone configuration only; the PP head runs ROCm0.
|
|||||||
6/ABRT, systemd restart, ~503 during reload). DSpark reuses the DFlash
|
6/ABRT, systemd restart, ~503 during reload). DSpark reuses the DFlash
|
||||||
block-diffusion machinery, which shares one draft context across
|
block-diffusion machinery, which shares one draft context across
|
||||||
parallel slots; concurrent block drafting faults in HIP stream sync.
|
parallel slots; concurrent block drafting faults in HIP stream sync.
|
||||||
This is the same multi-slot bug class that retired `draft-dflash`
|
This is the same multi-slot bug class that retired `draft-dflash` (premature
|
||||||
(premature EOS). The crash shows on 16k concurrent streams, not on a
|
EOS, retired 2026-08-14). The crash shows on 16k concurrent streams, not on a
|
||||||
67k pair — concurrency is the trigger, not size. Fix: PARALLEL=1
|
67k pair — concurrency is the trigger, not size. Fix: PARALLEL=1 (requests
|
||||||
(requests queue safely). Retired the same day.
|
queue safely). Retired the same day.
|
||||||
- **2026-08-15 to 08-16: `--spec-default` (ngram-mod), Vulkan0** — n_match
|
- **2026-08-15 to 08-16: `--spec-default` (ngram-mod), Vulkan0** — n_match
|
||||||
24 / n_min 48 / n_max 64, draftless, PARALLEL=2 (2 x 32k parallel stream
|
24 / n_min 48 / n_max 64, draftless, PARALLEL=2 (2 x 32k parallel stream
|
||||||
test passes). Chosen for parallel safety after DSpark; kept as the
|
test passes). Chosen for parallel safety after DSpark; kept as the
|
||||||
fallback under MTP in the current config.
|
fallback under MTP in the 2026-08-17 shape.
|
||||||
|
|
||||||
## Benchmark Method
|
## Benchmark Method
|
||||||
|
|
||||||
@@ -146,19 +120,19 @@ ubatch 256, single slot, on scratch port 7892.
|
|||||||
|
|
||||||
Verdict: at very high context, Vulkan0 decodes **48% faster** (5.68 vs
|
Verdict: at very high context, Vulkan0 decodes **48% faster** (5.68 vs
|
||||||
3.83 t/s); ROCm0 prefills 12% faster. Generation is the interactive cost
|
3.83 t/s); ROCm0 prefills 12% faster. Generation is the interactive cost
|
||||||
(users stream tokens). This verdict applies to the standalone
|
(users stream tokens). This verdict applies to the standalone configuration; the PP
|
||||||
configuration; the PP head runs ROCm0 (HIP registers before Vulkan).
|
head runs ROCm0 — HIP registers before Vulkan and the iGPU dedup rule (the llama.cpp
|
||||||
|
PR #23897 workaround) keeps the first backend's device.
|
||||||
Both `tg_3s` values were rock-steady across the run (3.83 and 5.67 t/s).
|
Both `tg_3s` values were rock-steady across the run (3.83 and 5.67 t/s).
|
||||||
High-context decode collapses on both backends versus ~25 t/s at 16k ctx;
|
High-context decode collapses on both backends versus ~25 t/s at 16k ctx;
|
||||||
that is the long-context attention penalty, not a spec artifact.
|
that is the long-context attention penalty, not a spec artifact.
|
||||||
|
|
||||||
## Production Configuration
|
## Where the tunables live
|
||||||
|
|
||||||
The live tunables live in `scripts/frank-dragoon.env` (head) and
|
That era's head and worker env/units are listed (and marked deleted) in
|
||||||
`scripts/frank-pp-worker.env` (worker) in this repo. The Production
|
[[Pipeline Parallelism/Qwen3.8 PP Deployment]] §Files. `scripts/frank-dragoon.env`
|
||||||
state section at the top of this page records the current values: Q6_K
|
is no longer a PP-head env at all — it is the halogen-flash-server trio of the
|
||||||
model + standalone MTP draft, split 0.68/0.32, 262144 ctx, PARALLEL=1,
|
current era, which [[frank-dragoon]] owns.
|
||||||
q8_0/f16 KV.
|
|
||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ Related pages:
|
|||||||
| 2 | MTP `n_max` explicit 4–5 + Q4_0 draft head | +5–15% on the spec share | restart, 1.56 GB file | test 08-16 |
|
| 2 | MTP `n_max` explicit 4–5 + Q4_0 draft head | +5–15% on the spec share | restart, 1.56 GB file | test 08-16 |
|
||||||
| 3 | Plain `Q8_0` A/B vs UD-Q8_K_XL (same 8 bits) | dequant ALUs may differ | restart, 29 GB file | test 08-16 |
|
| 3 | Plain `Q8_0` A/B vs UD-Q8_K_XL (same 8 bits) | dequant ALUs may differ | restart, 29 GB file | test 08-16 |
|
||||||
| 4 | Prefill path: ROCm backend + tuned ubatch/threads-batch | 2–3× prefill for agentic turns | per-workload backend choice | partial data |
|
| 4 | Prefill path: ROCm backend + tuned ubatch/threads-batch | 2–3× prefill for agentic turns | per-workload backend choice | partial data |
|
||||||
| 5 | TTM `pages_limit` raised to 114 GiB | removes the hard VRAM ceiling; the full 262k f16 KV plus the Q8 AGENT payload, MTP draft, and mmproj fit in one slot | modprobe, set live 2026-08-25 | applied (29,883,536 pages) |
|
| 5 | TTM `pages_limit` raised | removes the hard VRAM ceiling; the full 262k f16 KV plus the Q8 AGENT payload, MTP draft, and mmproj fit in one slot | modprobe, set live 2026-08-25 | applied — value and file: [[Dankclaw System Specs]] (Memory) |
|
||||||
| 6 | Vulkan ICD pinning + loader-layer disable | robustness; small | service env vars | test 08-16 |
|
| 6 | Vulkan ICD pinning + loader-layer disable | robustness; small | service env vars | test 08-16 |
|
||||||
|
|
||||||
Everything else (quantization downgrade, NVFP4, larger drafts) is documented
|
Everything else (quantization downgrade, NVFP4, larger drafts) is documented
|
||||||
@@ -62,32 +62,32 @@ Consequences of the hybrid design:
|
|||||||
cannot be prefix-cached the way attention KV can. Every agentic turn
|
cannot be prefix-cached the way attention KV can. Every agentic turn
|
||||||
re-prefills the whole conversation. **Prefill is the hidden cost of
|
re-prefills the whole conversation. **Prefill is the hidden cost of
|
||||||
agentic use**, and it is the dominant cost we have not yet optimized.
|
agentic use**, and it is the dominant cost we have not yet optimized.
|
||||||
3. **MTP is native and strong.** The model ships a nextn head; our matrix
|
3. **MTP is native and strong.** The model ships a nextn head; on Vulkan at 16k
|
||||||
measured 13.3 t/s vs 7.2 t/s (no spec) at 16k on Vulkan.
|
it roughly doubled the no-spec rate (the pair of figures is
|
||||||
|
[[qwen3.8-spec-matrix]]'s realistic-prompt table).
|
||||||
|
|
||||||
## Current production state (baseline)
|
## Baseline this page optimized (2026-08-15)
|
||||||
|
|
||||||
`frank-dragoon` (Dankclaw, Vulkan0, 2026-08-15):
|
`frank-dragoon` then ran llama.cpp on the iGPU with the UD-Q8_K_XL target
|
||||||
|
(bundled MTP head), `--spec-default` ngram-mod under a draft-mtp first link, two
|
||||||
- Model: UD-Q8_K_XL, 31.5 GB, bundled MTP head.
|
262144 slots, q8_0 KV, batch 8192 / ubatch 256, threads 12. That era's ledger is
|
||||||
- `--spec-default` (ngram-mod) with draft-mtp first in the chain.
|
[[frank-dragoon]]'s; what this page keeps is the shape of the problem: the
|
||||||
- 2 parallel slots × 262144 ctx, KV q8_0, batch 8192, ubatch 256,
|
service occupied **28 GiB of the then 96 GiB firmware VRAM carve, ~74 GiB
|
||||||
threads 12, `-dio` off, `--fit off`.
|
idle**, decode held ~25 t/s at 16k and collapsed at 262k depth
|
||||||
- Measured: ~25 t/s at 16k ctx; 5.68 t/s at 262k ctx; prefill 302 t/s @64k
|
([[qwen3.8-spec-matrix]] §High-Context Backend Comparison), and prefill was the
|
||||||
(Vulkan) vs 410 t/s @64k (ROCm, same build).
|
unoptimized agentic cost (section 4).
|
||||||
- GPU: 28 GiB of 96 GiB GTT used. **74 GiB sits idle.**
|
|
||||||
|
|
||||||
## The levers, in detail
|
## The levers, in detail
|
||||||
|
|
||||||
### 1. Pipeline-parallel to the RTX 3090 (biggest win)
|
### 1. Pipeline-parallel to the RTX 3090 (biggest win)
|
||||||
|
|
||||||
The 3090 on Dankserver is idle (serves a 22 GB MoE small-model service with
|
The 3090 on Dankserver had headroom that night (it carried the day's small-model
|
||||||
~2.4 GB free). llama.cpp RPC splits the model by **layers**: each device
|
service with a couple of GiB free — that card's eras are [[frank-zealot]]'s).
|
||||||
runs its layer range, hidden states cross the 2.5 GbE ethernet once per
|
llama.cpp RPC splits the model by **layers**: each device runs its layer range,
|
||||||
token. The per-token transfer is ~41 KiB (5120-wide f32 hidden state, both
|
hidden states cross the 2.5 GbE ethernet once per token. The per-position wire
|
||||||
directions); at ~0.5 ms LAN RTT the bandwidth cost is negligible — the split
|
bill is measured in [[Pipeline Parallelism/Ethernet Bandwidth Math]] §0; at
|
||||||
is latency-bound, not bandwidth-bound (see
|
~0.5 ms LAN RTT the bandwidth cost is negligible — the split is latency-bound,
|
||||||
[Ethernet Bandwidth Math](Pipeline%20Parallelism/Ethernet%20Bandwidth%20Math.md)).
|
not bandwidth-bound.
|
||||||
|
|
||||||
Why this is a real speedup and not just "two GPUs": the 3090 does
|
Why this is a real speedup and not just "two GPUs": the 3090 does
|
||||||
matmuls roughly 2–3× faster per layer than the 8060S (936 vs 512 GB/s
|
matmuls roughly 2–3× faster per layer than the 8060S (936 vs 512 GB/s
|
||||||
@@ -95,58 +95,32 @@ memory, 80 vs 40 CUs). A 50/50 layer split balances per-layer latency, so
|
|||||||
each token step takes ≈ max(half-on-3090, half-on-Strix) + one RTT instead
|
each token step takes ≈ max(half-on-3090, half-on-Strix) + one RTT instead
|
||||||
of all-64-layers-on-Strix.
|
of all-64-layers-on-Strix.
|
||||||
|
|
||||||
Design decisions (verified in b10433 source, 2026-08-15):
|
Every decision this led to is written once, in
|
||||||
|
[[Pipeline Parallelism/Qwen3.8 PP Deployment]] §Gotchas (with the 4B smoke test
|
||||||
- **Head on Dankclaw, worker on Dankserver.** The 31.5 GB model file stays
|
that proved each): head on the box that already holds the model file, **no
|
||||||
on the head; the worker receives its tensor share over the wire at load
|
`--device` on the head** (setting it silently drops RPC), the fixed
|
||||||
(with `-c` it caches the tensors locally after the first load).
|
HIP-before-Vulkan device selection, the reported-free-memory split trap, the
|
||||||
- **Head must NOT pass `--device`.** When `params.devices` is set,
|
identical-build requirement, and `-dio` on the head — the last one visorcraft's
|
||||||
`llama_prepare_model_devices` builds the device list from exactly those
|
Strix finding, matching our own 28 GiB load-stall history. Scripts and the
|
||||||
devices and the RPC device is silently dropped (`--rpc` becomes a no-op).
|
morning runbook are on the same page.
|
||||||
Default device selection inserts RPC servers **at the front** of the list.
|
|
||||||
- **The local iGPU side runs on ROCm, not Vulkan.** Default selection walks
|
|
||||||
registered backends in order; HIP registers before Vulkan, and the iGPU
|
|
||||||
dedup rule (PR #23897 workaround) keeps the first backend's device.
|
|
||||||
Verified live 2026-08-15: device list `[RPC0, ROCm0]`, Vulkan0 never
|
|
||||||
listed. Consequence: the Strix half runs on the ROCm backend — better
|
|
||||||
prefill, ~3% slower decode than Vulkan0 (measured on this box).
|
|
||||||
A second head build (`/home/dank/llama.cpp/build-vulkan-rpc`, HIP off,
|
|
||||||
Vulkan on, RPC on) was built the same night for an A/B; with it the
|
|
||||||
device list becomes `[RPC0, Vulkan0]`.
|
|
||||||
- **Default split is proportional to *reported free memory*, which is wrong
|
|
||||||
here.** The Strix reports up to 96 GiB (GTT ceiling) vs the 3090's 24 GB,
|
|
||||||
so the default lands ~20/80 in favor of the slow device (verified with a
|
|
||||||
4B smoke test: 4 of 36 layers on the 3090). We pin `--tensor-split 1,1`
|
|
||||||
(50/50) explicitly.
|
|
||||||
- **`-dio` (direct I/O) on the head.** Large model + RPC load hangs without
|
|
||||||
it (visorcraft Strix finding; matches our 28 GiB load-stall history).
|
|
||||||
- **Version skew hangs the handshake.** Worker built at the identical
|
|
||||||
commit (9b05354ec / b10433) in a worktree
|
|
||||||
`/home/dank/llama-cpp-rpc` on Dankserver — production b10121 build
|
|
||||||
untouched.
|
|
||||||
|
|
||||||
Smoke test (2026-08-15, 4B model, 0.2/0.8 split, production untouched):
|
|
||||||
worker VRAM rose ~819 MiB (real split), 95 t/s prefill, 58.8 t/s decode on
|
|
||||||
the tiny model. RTT on the link: ~0.3–0.5 ms.
|
|
||||||
|
|
||||||
Full design, scripts, and morning runbook:
|
|
||||||
[Qwen3.8 PP Deployment](Pipeline%20Parallelism/Qwen3.8%20PP%20Deployment.md).
|
|
||||||
|
|
||||||
### 2. Speculative-decoding tuning (same bits, free tokens)
|
### 2. Speculative-decoding tuning (same bits, free tokens)
|
||||||
|
|
||||||
- **MTP `n_max`.** Production leaves `--spec-draft-n-max` unset. Our matrix
|
- **MTP `n_max`.** Production left `--spec-draft-n-max` unset; the fleet matrix
|
||||||
(Vulkan, 16k) found 13.3 t/s at the tested setting vs 7.2 without spec;
|
(Vulkan, 16k, realistic prompt) found the depth-5 peak against the no-spec
|
||||||
the published Strix tuning curve peaks at n_max 3–4 (30.3 t/s at 4 vs
|
baseline — both figures are [[qwen3.8-spec-matrix]]'s realistic-prompt table.
|
||||||
28.9 at 3 vs 29.9 at 5). The PP env sets **4** explicitly; the matrix
|
The published Strix tuning curve peaks at n_max 3–4 (30.3 t/s at 4 vs 28.9 at
|
||||||
re-tests 3/4/5 on the real split.
|
3 vs 29.9 at 5). The PP env set **4** explicitly; the matrix re-tested 3/4/5
|
||||||
|
on the real split.
|
||||||
- **Q4_0 draft head.** The published Strix card measured a standalone
|
- **Q4_0 draft head.** The published Strix card measured a standalone
|
||||||
Q4_0 MTP head ~6–10% faster than Q8_0 for the same acceptance (the draft
|
Q4_0 MTP head ~6–10% faster than Q8_0 for the same acceptance (the draft
|
||||||
head is a 248k-vocab output projection; cheaper dequant, same accuracy).
|
head is a 248k-vocab output projection; cheaper dequant, same accuracy).
|
||||||
The bundled head inside UD-Q8_K_XL is Q8-class; the standalone
|
The bundled head inside UD-Q8_K_XL is Q8-class; the standalone
|
||||||
`ggml-org/mtp-Qwen3.8-27B-Q4_0.gguf` (1.56 GB) is being downloaded for
|
`ggml-org/mtp-Qwen3.8-27B-Q4_0.gguf` (1.56 GB) is being downloaded for
|
||||||
an A/B via `--spec-draft-model`.
|
an A/B via `--spec-draft-model`.
|
||||||
- **Ngram-mod fallback stays.** It is the only spec type that survived
|
- **Ngram-mod fallback stays.** It is the only spec type that survived parallel
|
||||||
parallel load (DSpark crashed ROCm, DFlash corrupts multi-slot).
|
load; the DSpark ROCm fault and the DFlash multi-slot corruption are timed and
|
||||||
|
explained on [[qwen3.8-spec-matrix]].
|
||||||
|
|
||||||
### 3. Same-bit quant A/B: UD-Q8_K_XL vs plain Q8_0
|
### 3. Same-bit quant A/B: UD-Q8_K_XL vs plain Q8_0
|
||||||
|
|
||||||
@@ -162,10 +136,10 @@ zero quality cost.
|
|||||||
Every agentic turn re-prefills the whole conversation (no prefix caching for
|
Every agentic turn re-prefills the whole conversation (no prefix caching for
|
||||||
hybrid state, upstream). Levers:
|
hybrid state, upstream). Levers:
|
||||||
|
|
||||||
- **Backend choice per workload.** Measured @64k on this box (b10433):
|
- **Backend choice per workload.** Measured @64k on this box (b10433, the era
|
||||||
ROCm 410 t/s vs Vulkan 302 t/s prefill; Vulkan 25.1 vs ROCm 24.3 t/s
|
[[frank-dragoon]] owns): ROCm 410 t/s vs Vulkan 302 t/s prefill; Vulkan 25.1
|
||||||
decode. For chat-heavy use: Vulkan. For agentic/batch-heavy use: ROCm.
|
vs ROCm 24.3 t/s decode. For chat-heavy use: Vulkan. For agentic/batch-heavy
|
||||||
The PP head (ROCm side) gets this for free.
|
use: ROCm. The PP head (ROCm side) gets this for free.
|
||||||
- **ubatch/threads-batch.** Production runs ubatch 256. Larger ubatches
|
- **ubatch/threads-batch.** Production runs ubatch 256. Larger ubatches
|
||||||
(512/1024) fill the iGPU better during prefill; `--threads-batch` for
|
(512/1024) fill the iGPU better during prefill; `--threads-batch` for
|
||||||
the CPU-bound tail. Untested at prefill scale on this box — matrix item.
|
the CPU-bound tail. Untested at prefill scale on this box — matrix item.
|
||||||
@@ -175,14 +149,14 @@ hybrid state, upstream). Levers:
|
|||||||
|
|
||||||
### 5. OS level (from the Improvements doc, re-verified 2026-08-15)
|
### 5. OS level (from the Improvements doc, re-verified 2026-08-15)
|
||||||
|
|
||||||
- **TTM `pages_limit` is now 114 GiB (29,883,536 pages)** — applied 2026-08-25.
|
- **TTM `pages_limit`** — the raise itself (value, live write, modprobe file,
|
||||||
Written live to `/sys/module/ttm/parameters/pages_limit` (no reboot required)
|
date) is one row on [[Dankclaw System Specs]] (Memory). What matters to this
|
||||||
and persisted in `/etc/modprobe.d/ttm.conf`. The full 262k f16 KV cache plus
|
page is the mechanism: the driver-reported 96 GiB VRAM carve-out (VGM/SVM
|
||||||
the ~28 GB Q8 AGENT payload, MTP draft, and mmproj now fit in one slot. The
|
pool) was never the ceiling — the TTM kernel page map was, and until it was
|
||||||
load-stall risk from the old 15 GiB cap is resolved. Note: 96 GiB is the
|
raised a 262k f16 KV cache plus a ~28 GB payload could not load in one slot.
|
||||||
driver-reported VRAM carve-out (VGM/SVM pool); the TTM pages_limit is the
|
- **Boot line** — IOMMU policy on this host is [[dankclaw-iommu-translation-off]]'s
|
||||||
kernel page map that was the real ceiling.
|
and [[Dankclaw System Specs]]'s; it has changed twice since this lever was
|
||||||
- `iommu=pt` — verified present on the kernel cmdline. Done.
|
written, so no era-scoped reading of `/proc/cmdline` belongs here.
|
||||||
- **Vulkan ICD pinning** — `radeon_icd.json` exists; no `VK_ICD_FILENAMES`
|
- **Vulkan ICD pinning** — `radeon_icd.json` exists; no `VK_ICD_FILENAMES`
|
||||||
or loader-layer env is set. Pinning the radeon ICD and disabling loader
|
or loader-layer env is set. Pinning the radeon ICD and disabling loader
|
||||||
layers (`VK_LOADER_LAYERS_DISABLE=all`) is the recommended Strix
|
layers (`VK_LOADER_LAYERS_DISABLE=all`) is the recommended Strix
|
||||||
@@ -240,8 +214,8 @@ Per config: `pp-test.sh bench 4` (4k prompt / 256 out) and `bench 16`
|
|||||||
(16k / 256). Report: decode t/s (server print_timing), prefill t/s, MTP
|
(16k / 256). Report: decode t/s (server print_timing), prefill t/s, MTP
|
||||||
acceptance, worker VRAM, head GTT usage.
|
acceptance, worker VRAM, head GTT usage.
|
||||||
|
|
||||||
Success bar: **≥ 30 t/s at 4k and ≥ 20 t/s at 16k decode** (vs 25 t/s
|
Success bar: **≥ 30 t/s at 4k and ≥ 20 t/s at 16k decode**, against the
|
||||||
production @16k) with the same 8-bit model.
|
production @16k bar in the Baseline section, with the same 8-bit model.
|
||||||
|
|
||||||
## Sources
|
## Sources
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,9 @@ timestamp: 2026-10-05T00:00:00-07:00
|
|||||||
|
|
||||||
# vLLM Boot Forensics and Config Interrogation
|
# vLLM Boot Forensics and Config Interrogation
|
||||||
|
|
||||||
For serve-script vLLM endpoints (frank-archon/qwen-fp8 on dankserver, any
|
For serve-script vLLM endpoints (the vLLM eras of [[frank-archon]] — that page's
|
||||||
`podman rm -f` + restart service).
|
Eras table is which ones; any endpoint that runs `podman rm -f` + a restart
|
||||||
|
service).
|
||||||
|
|
||||||
## 1. Capture the true cause — the journal, not `podman logs`
|
## 1. Capture the true cause — the journal, not `podman logs`
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ From the 111 GiB GGUF (`mradermacher/Qwen3.8-Flash-Next-Uncensored-i1-Q4_K_M`,
|
|||||||
- 48 layers, of which **12 are full attention** (indices `[3,7,11,15,19,23,27,31,35,39,43,47]`,
|
- 48 layers, of which **12 are full attention** (indices `[3,7,11,15,19,23,27,31,35,39,43,47]`,
|
||||||
every 4th — `full_attention_interval = 4`) and 36 are GDN/linear.
|
every 4th — `full_attention_interval = 4`) and 36 are GDN/linear.
|
||||||
- Only the 12 attention layers carry KV. At the engine's measured 28 KiB per
|
- Only the 12 attention layers carry KV. At the engine's measured 28 KiB per
|
||||||
position, a 200k-token conversation reads **5.5 GiB of KV per token**.
|
position, a 200k-token conversation holds **5.5 GiB of KV**.
|
||||||
|
|
||||||
- A layer split moves **whole layers**, so it moves ~1.62 GiB of experts with
|
- A layer split moves **whole layers**, so it moves ~1.62 GiB of experts with
|
||||||
every layer (75 GiB / 48). Attention layers are spread across the whole depth
|
every layer (75 GiB / 48). Attention layers are spread across the whole depth
|
||||||
@@ -82,10 +82,12 @@ Real placement in the split runs, sampled from `nvidia-smi` during the run:
|
|||||||
split is genuine, not a mislabelled single-device run (see Finding 5 for why
|
split is genuine, not a mislabelled single-device run (see Finding 5 for why
|
||||||
that check is mandatory here).
|
that check is mandatory here).
|
||||||
|
|
||||||
Reference points on the same silicon: halogen (deployed) ≈ **25 tok/s** at real
|
Reference points, all era readings rather than measurements of this run: the
|
||||||
contexts; the retired ik hybrid 3.8–4.6 tok/s; mainline with the trunk on the
|
deployed halogen shape at ≈ **25 tok/s** at real contexts and the retired ik
|
||||||
3090 and CPU experts 1.01 tok/s (2026-09-15); the CPU expert path's prefill
|
hybrid at 3.8–4.6 tok/s (both are [[frank-dragoon]] eras, and that page's Eras
|
||||||
ceiling 192 tok/s.
|
rows are where those shapes live); mainline with the trunk on the 3090 and CPU
|
||||||
|
experts at 1.01 tok/s (2026-09-15, this page's own earlier pass); the CPU expert
|
||||||
|
path's prefill ceiling at 192 tok/s.
|
||||||
|
|
||||||
## Finding 1 — per-tensor placement across devices is killed by one flag: `-ot`
|
## Finding 1 — per-tensor placement across devices is killed by one flag: `-ot`
|
||||||
|
|
||||||
@@ -248,15 +250,16 @@ distinguishes a real split from a mislabelled sweep.
|
|||||||
## Conclusion
|
## Conclusion
|
||||||
|
|
||||||
The fleet's answer is unchanged — **two independent endpoints**
|
The fleet's answer is unchanged — **two independent endpoints**
|
||||||
([[frank-dragoon]] on the iGPU via halogen,
|
([[frank-dragoon]] on the iGPU, [[frank-zealot]] alone on the 3090; each page
|
||||||
[[frank-zealot]] holding a whole 27B in the 3090's 24 GB) — but two
|
owns what its card holds) — but two claims from the first round of this
|
||||||
claims from the first round of this experiment are now corrected:
|
experiment are now corrected:
|
||||||
|
|
||||||
1. **Cross-vendor layer split is possible** (measured: CUDA0 + Vulkan1, 27.23
|
1. **Cross-vendor layer split is possible** (measured: CUDA0 + Vulkan1, 27.23
|
||||||
tok/s and 268.5 t/s prefill at 64k). It is not a regime change (+7 % decode),
|
tok/s and 268.5 t/s prefill at 64k). It is not a regime change (+7 % decode),
|
||||||
and it costs the 3090 ~15 GiB — which this fleet spends on the vision endpoint
|
and it costs the 3090 ~15 GiB — memory this fleet instead spends on the
|
||||||
(`frank-zealot` holds 22.4 of the card's 24.6 GiB). An operator who wants the
|
vision endpoint, whose settled footprint is an Eras row on
|
||||||
7 % must give up the fleet's only image-capable endpoint.
|
[[frank-zealot]]. An operator who wants the 7 % must give up the fleet's only
|
||||||
|
image-capable endpoint.
|
||||||
2. **Per-tensor placement across two devices is impossible while `-ot` is used**,
|
2. **Per-tensor placement across two devices is impossible while `-ot` is used**,
|
||||||
for a scheduler-mechanical reason, regardless of driver or vendor mix.
|
for a scheduler-mechanical reason, regardless of driver or vendor mix.
|
||||||
|
|
||||||
@@ -316,11 +319,13 @@ Operational notes for the next run:
|
|||||||
- Restarting frank-dragoon needs the quadlet source back in
|
- Restarting frank-dragoon needs the quadlet source back in
|
||||||
`~/.config/containers/systemd/` plus `daemon-reload`; the generator re-creates
|
`~/.config/containers/systemd/` plus `daemon-reload`; the generator re-creates
|
||||||
the unit from that file only. After the restore (and the host reboot, see the
|
the unit from that file only. After the restore (and the host reboot, see the
|
||||||
landmines) the ledger read `400384 positions, ~27.2 GiB` against a 33.5 GiB
|
landmines) its boot ledger read `400384 positions, ~27.2 GiB` against a 33.5
|
||||||
budget — no clamp — with 12.3 GiB left for everything else (14.7 GiB before
|
GiB budget — no clamp — with 12.3 GiB left for everything else (14.7 GiB
|
||||||
the reboot: the same model, a more fragmented host afterwards — the engine
|
before the reboot: the same model, a more fragmented host afterwards — the
|
||||||
reported 240 free contiguous 2 MiB blocks against 475 earlier). Both endpoints
|
engine reported 240 free contiguous 2 MiB blocks against 475 earlier). That
|
||||||
answered `/health` and served `/v1/models` under their names.
|
ledger is an era reading of [[frank-dragoon]]; the block-census lesson it
|
||||||
|
teaches is on [[Llama Cpp Serving Sizing]]. Both endpoints answered `/health`
|
||||||
|
and served `/v1/models` under their names.
|
||||||
|
|
||||||
|
|
||||||
## Smaller-quant check: Q4_K_S against the recorded Q4_K_M numbers
|
## Smaller-quant check: Q4_K_S against the recorded Q4_K_M numbers
|
||||||
@@ -393,10 +398,10 @@ expert mass) — 580 × 3 MiB slabs:
|
|||||||
| *the same bytes computed in host RAM at 256 GB/s* | 7.1 ms | the link is **31× slower** than the memory behind it |
|
| *the same bytes computed in host RAM at 256 GB/s* | 7.1 ms | the link is **31× slower** than the memory behind it |
|
||||||
|
|
||||||
Against this host's measured alternatives — **20.46 tok/s** for llama.cpp with
|
Against this host's measured alternatives — **20.46 tok/s** for llama.cpp with
|
||||||
the experts *computed* on the CPU (link carries activations only), 25 for
|
the experts *computed* on the CPU (link carries activations only, config B′
|
||||||
halogen, 26.5 for mainline on the iGPU — an engine that *streams* experts across
|
above), 25 for the halogen shape deployed that day ([[frank-dragoon]]), 26.5 for
|
||||||
this link loses by 3–5×, and the port's x8 ceiling would only double it (≈7–9
|
mainline on the iGPU — an engine that *streams* experts across this link loses
|
||||||
tok/s).
|
by 3–5×, and the port's x8 ceiling would only double it (≈7–9 tok/s).
|
||||||
|
|
||||||
For the specific engine that raised the question: FreeToken v0.1.2 keeps expert
|
For the specific engine that raised the question: FreeToken v0.1.2 keeps expert
|
||||||
weights in host RAM with an LRU GPU cache — exactly this streaming shape — and
|
weights in host RAM with an LRU GPU cache — exactly this streaming shape — and
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ that endpoint's page, not a page.
|
|||||||
|---|---|
|
|---|---|
|
||||||
| [[frank-medium-batch-ubatch]] | llama-bench sweep of --batch-size against --ubatch-size on frank-medium (2x Radeon AI PRO R9700, layer split) at the… |
|
| [[frank-medium-batch-ubatch]] | llama-bench sweep of --batch-size against --ubatch-size on frank-medium (2x Radeon AI PRO R9700, layer split) at the… |
|
||||||
| [[frank-medium-llamacpp-dflash2]] | The former ACTIVE frank-medium deployment since 2026-09-16 (model swapped 2026-09-19) — mainline llama.cpp on… |
|
| [[frank-medium-llamacpp-dflash2]] | The former ACTIVE frank-medium deployment since 2026-09-16 (model swapped 2026-09-19) — mainline llama.cpp on… |
|
||||||
| [[frank-medium-model-swap]] | How to swap the checkpoint behind the frank-medium endpoint (Dankserver :7770, vllm-radiance TP=2) — the streamlining… |
|
| [[frank-medium-model-swap]] | RETIRED-era swap procedure for the frank-medium endpoint (`:7770` is now [[frank-archon]]) — the… |
|
||||||
| [[frank-medium-radiance-mxfp4]] | ACTIVE frank-medium runbook — vllm-radiance serving hugypufy/Swift-Qwen3.8-27B-PARO-MXFP6 (ParoQuant MXFP6 W4A8,… |
|
| [[frank-medium-radiance-mxfp4]] | RETIRED frank-medium era runbook — vllm-radiance serving hugypufy/Swift-Qwen3.8-27B-PARO-MXFP6 (ParoQuant MXFP6 W4A8,… |
|
||||||
| [[frank-medium-rocmfpx]] | charlie12345/ROCmFPX llama.cpp serving kingjones777/Qwen3.8-27B-ROCmFPX-Q8_0-AGENT-GGUF as frank-medium on Dankserver… |
|
| [[frank-medium-rocmfpx]] | charlie12345/ROCmFPX llama.cpp serving kingjones777/Qwen3.8-27B-ROCmFPX-Q8_0-AGENT-GGUF as frank-medium on Dankserver… |
|
||||||
| [[frank-npu]] | The retired FastFlowLM endpoint on Dankclaw's XDNA2 NPU — what it served, why it died on 2026-09-11 with the… |
|
| [[frank-npu]] | The retired FastFlowLM endpoint on Dankclaw's XDNA2 NPU — what it served, why it died on 2026-09-11 with the… |
|
||||||
| [[frank-redo-2026-08-17]] | This page records the full redo of the inference fleet on 2026-08-17. |
|
| [[frank-redo-2026-08-17]] | This page records the full redo of the inference fleet on 2026-08-17. |
|
||||||
|
|||||||
@@ -3,23 +3,20 @@
|
|||||||
## 2026-10-18
|
## 2026-10-18
|
||||||
- **frank-zealot resliced to two windows of exact KV (Frank's call, PR #21).**
|
- **frank-zealot resliced to two windows of exact KV (Frank's call, PR #21).**
|
||||||
`--ctx-size 786432 --parallel 3` at q8_0 K+V → **`524288 / 2` at f16 K+V**, so
|
`--ctx-size 786432 --parallel 3` at q8_0 K+V → **`524288 / 2` at f16 K+V**, so
|
||||||
both remaining conversations keep the native 262,144 window and the
|
both remaining conversations keep the native 262,144 window and the compaction
|
||||||
compaction hub reads exact K and V. Halving the pool is what funds it: the
|
hub reads exact K and V. **Halving the pool is what funds exact KV** — the law
|
||||||
f16 pair is 32,768 B/token over the 8 full-attention layers = 16,384.00 MiB,
|
that came out of it is that a KV byte rate belongs to the payload it was
|
||||||
while the old 786,432-position pool would have needed ~24,576 MiB of KV alone
|
measured on: the doc's old "f16 needs 26,112 MiB and cannot boot" figure was
|
||||||
on a card that leaves 24,576 addressable. Measured boot: KV **16,384.00**,
|
the 27B's 34,816 B/token applied to the 9B. The measured boot ledger is on
|
||||||
RS **100.50** (2 cells), compute 1,408.06 + 1,088.07, settled `nvidia-smi`
|
[[frank-zealot]] (Current shape), which is also where the 32,768 B/token
|
||||||
**21,176 used / 2,949 free**, `n_ctx_slot = 262144`, `DropInPaths` empty. The
|
derivation and the seam's fit gate live.
|
||||||
doc's old "f16 needs 26,112 MiB and cannot boot" figure was the 27B's
|
- **Rates are floors, and that is recorded as such.** The measurement window
|
||||||
34,816 B/token applied to the 9B — corrected in the runbook.
|
had another consumer on the other slot (56 prompts in three minutes, 96 %
|
||||||
- **Rates are floors, and that is recorded as such.** The endpoint had another
|
GPU-util) — the exact condition the bench window exists to exclude — so every
|
||||||
consumer for the whole measurement window (56 prompts on the other slot in
|
rate taken that evening is recorded on [[frank-zealot]] as a **FLOOR**, not as
|
||||||
three minutes, 96 % GPU-util), so single-stream decode came back 134.1–141.5
|
the shape's rate, with the instruction to re-measure with the box quiet before
|
||||||
(145.8/163.2 in a lighter minute) against the 3-slot record of 168.7,
|
a figure is carried anywhere. That is the honest shape of a number measured
|
||||||
two-stream aggregate 256.6–265.1 against ≈300 across three, and prefill
|
beside live traffic.
|
||||||
**3,159.5 at 106,282** beat the record's 2,877 while contended. Per-stream
|
|
||||||
concurrency improved (≈130 each vs 102.8); a clean re-measure needs the box
|
|
||||||
quiet.
|
|
||||||
- **Instrument correction (fleet law).** On the PrismML fork build 10777 the raw
|
- **Instrument correction (fleet law).** On the PrismML fork build 10777 the raw
|
||||||
`/completion` path answers **500 "The model produced output that does not
|
`/completion` path answers **500 "The model produced output that does not
|
||||||
match the expected Content-only format"** for a greedy `ignore_eos` run, so
|
match the expected Content-only format"** for a greedy `ignore_eos` run, so
|
||||||
|
|||||||
Reference in New Issue
Block a user