Files
serverAppConfigs/scripts/frank-primary.env
T
Frank 5d632bbaea frank-primary: pin the drafter to ROCm1 (the last-layers card)
The shared MTP head borrows the main model output head, which a -ts 1,1
layer split places on ROCm1. With tensor overrides set, n_copies==1 in the
draft's scheduler, and a borrowed output.weight in a ROCm1 buffer aborts the
draft graph (ggml-backend.cpp:941) when the draft context is on ROCm0 —
the unit crash-looped 4x at ~12 s per attempt during the 2026-09-26 cutover.
Probed live on the host: ROCm0 aborts identically, ROCm1 loads and serves.
2026-09-26 20:49:04 -07:00

89 lines
4.5 KiB
Bash

# frank-primary — unsloth llama.cpp (b11030-mix prebuilt, ROCm gfx120X)
# serving unsloth/Qwen3.8-Flash-Next-GGUF at Q8_0 on the two Radeon AI PRO
# R9700s (gfx1201), with the shared Q8_0 MTP drafter head, the BF16 vision
# projector, and the draft-mtp + ngram-mod spec chain.
#
# These are the tunables read by scripts/serve-frank-primary.sh. The flag
# list is owned by the serve script; this file only sets fleet values.
#
# DO NOT name a new tunable TEMP, HOST or GPU_MAX_HEAP_SIZE: the HIP
# runtime reads those bare (the 2026-08-13 TEMP incident). The bind address
# is BIND_HOST, not HOST — frank-large's env predates that lesson and gets
# away with it; do not copy the shape.
# The payload (scripts/download-frank-primary.sh): the serve script refuses
# to start without all six Q8_0 parts, the MTP head and the projector.
MODEL_ROOT=/home/dank/models/Qwen3.8-Flash-Next-GGUF
# The runtime: the unsloth b11030-mix prebuilt for gfx120X (the same
# b11030-mix build frank-large runs on gfx1151 — it bundles its own ROCm
# runtime, no host SDK gate).
RUNTIME_DIR=/home/dank/GitPackages/unsloth-llama-b11030
# Fleet endpoint: the port and alias the lucebox DS4.1 quadlet held before
# the 2026-09-26 swap, so no client, probe or models.yml entry changes
# address.
BIND_HOST=0.0.0.0
PORT=7770
# One conversation, the model's full native 262144 window.
CONTEXT_SIZE=262144
PARALLEL_SLOTS=1
# Spec chain: draft-mtp (the shared Q8_0 head) at depth 2, with the
# draftless ngram-mod matcher chained behind it. Depth 2 is the measured
# optimum class for this pair at long contexts (the retired Dankclaw
# Flash-Next deployment ran exactly this head at depth 2 with 0.83-0.92
# acceptance); each extra verified position re-batches the CPU expert reads,
# so depth buys less than bandwidth here.
SPEC_DRAFT_N_MAX=2
# Device placement. -ngl 999 puts every layer's non-overridden tensors on
# the GPUs; the big overrides then move the bandwidth-huge tensors to host
# RAM (computed there — the x4-pair measurement: streaming over PCIe loses,
# computing in RAM does not). OT_OVERRIDES is comma-separated
# <tensor-pattern>=<backend> pairs passed as repeated --override-tensor
# flags. Both overrides are pinned by the header dump of parts 2-3
# (2026-09-26, /home/dank/models/dump-gguf.py — GGUF v3, 512 experts
# top-10, qwen4exp.ple.ngram_size=3, heads_per_ngram=8):
# * exps=CPU — the routed experts (blk.*.ffn_*_exps.weight, ~100 GiB at
# Q8_0), read once per token; the CPU backend computes them from page
# cache.
# * per_layer_token_embd.weight=CPU — the 51.2B-element PLE n-gram table
# (dims [160, 320001536], Q8_0, 54.4 GiB — the whole of part 3):
# sparse row lookups, tiny PCIe traffic from CPU RAM. It doubles as
# the shared MTP head's borrow tensor — GPU-resident, the draft load
# crashes with "invalid vector subscript" (llama.cpp PR #28243) — so
# this override is REQUIRED, not just a placement choice. NEVER give
# it a GPU target (the 23 -> 13.4 t/s regression) and never --no-mmap
# (the table must stay page-cache-backed; anonymous memory
# cgroup-kills silently).
NGL=999
OT_OVERRIDES=exps=CPU,per_layer_token_embd.weight=CPU
TENSOR_SPLIT=1,1
# The drafter MUST sit on the SECOND R9700 (ROCm1): with -ts 1,1 the main
# model's output head lands on the last-layers card, and the shared MTP head
# BORROWS it. --override-tensor sets has_tensor_overrides(), which pins
# n_copies==1 in the draft's scheduler — a borrowed output.weight sitting in
# a ROCm1 buffer then aborts the draft graph with ggml-backend.cpp:941
# "pre-allocated tensor (output.weight) in a buffer (ROCm1) that cannot run
# the operation" when the draft is elsewhere (verified live 2026-09-26: the
# ROCm0 placement crash-looped 4x at ~12 s, ROCm1 loaded and served).
SPEC_DRAFT_DEVICE=ROCm1
# Batch geometry: logical batch 8192 with ubatch 512 — the measured optimum
# class on this fleet's ROCm stack (a bigger logical batch is free; compute
# buffers reserve at max graph size). ubatch 512 balances prefill
# throughput against the asymmetric compute-buffer cost on the card that
# holds the output layers and the drafter.
BATCH_SIZE=8192
UBATCH_SIZE=512
# Prompt-cache budget: 16 GiB. The KV itself is small (the hybrid
# DeltaNet/QSA pattern keeps a 262144 window a fraction of the full-ctx
# x all-layers number), so the prompt cache is the RAM-side spend that
# actually moves prefill on repeat traffic. Host RAM budget: ~175 GiB of
# expert pages + this cache + the server's own arenas inside 246 GiB.
CACHE_RAM=16384