frank-default-small: ncmoe 32 + ubatch 1024 from llama-bench sweep

Swept ncmoe(30..40) x ubatch(256..4096) on the RTX 3090 (Qwen3.6-35B-A3B
Q6_K_P, pp16384/tg512, fit-target 0). Key findings:
- Generation depends only on ncmoe: 40.9 (ncmoe40) .. 51.1 (ncmoe30);
  ubatch/batch do not affect decode at all.
- Prefill + graph VRAM scale with ubatch; logical batch is irrelevant.
- VRAM model (peak + 11.44GiB KV pool + 2.2GiB overhead) reproduces the
  historical OOMs: ncmoe32-ub2048 sums ~24.4GiB > 24.

Chosen state: ncmoe 32 (8 expert layers on GPU), batch 8192, ubatch 1024.
  gen ~48.7 t/s (+7% vs prior ncmoe 35), prefill ~766 t/s, ~1.0GiB headroom.
Alternates: ncmoe34-ub2048 (gen 46.4, pp 1221, 1.5GiB) for prefill-heavy;
  ncmoe32-ub768 (1.3GiB) if headroom matters most.
Docs: new frank-default-small-benchmark.md; synced deployment.md + specs.
This commit is contained in:
Frank
2026-08-13 22:56:24 -07:00
parent 0d09756430
commit 3c2db64a78
6 changed files with 145 additions and 11 deletions
+2 -2
View File
@@ -51,11 +51,11 @@ Dankserver is an NVIDIA GPU server for vLLM inference. The host runs Ubuntu 24.0
### Active Services
The active `frank-default-small` service (llama.cpp, `b10108+`) serves the HauhauCS Qwen3.6-35B-A3B uncensored `Q6_K_P` model on port 7770 with **ngram-mod** speculative decoding. It runs **4 parallel slots** at 200000 context each (pool 800000). Of the 40 layers' MoE expert weights, **35 sit on CPU** (`--n-cpu-moe 35`) while the remaining **5 layers' expert weights** are resident on GPU along with all non-expert tensors (`--gpu-layers all`). KV stays on GPU with K=`q8_0`, V=`f16`. Batch 8192 / ubatch 2048, `--ctx-checkpoints 4`, `--no-mmap`. At idle ~22.2 GB VRAM used, leaving an estimated **~1.8 GiB** headroom (up from ~870 MiB at `--n-cpu-moe 32`). Idle RAM ~32 GB of 62 GB.
The active `frank-default-small` service (llama.cpp, `b10108+`) serves the HauhauCS Qwen3.6-35B-A3B uncensored `Q6_K_P` model on port 7770 with **ngram-mod** speculative decoding. It runs **4 parallel slots** at 200000 context each (pool 800000). Of the 40 layers' MoE expert weights, **32 sit on CPU** (`--n-cpu-moe 32`) while the remaining **8 layers' expert weights** are resident on GPU along with all non-expert tensors (`--gpu-layers all`). KV stays on GPU with K=`q8_0`, V=`f16`. Batch 8192 / ubatch 1024, `--ctx-checkpoints 4`, `--no-mmap`. At idle ~23.0 GB VRAM used, leaving an estimated **~1.0 GiB** headroom (chosen by benchmark, see [[frank-default-small-benchmark]]). Idle RAM ~32 GB of 62 GB.
## Hardware Relevance
- 24 GB VRAM is close to saturated with this config. At idle ~22.2 GB used, leaving an estimated **~1.8 GiB** headroom at `--n-cpu-moe 35` (5 layers' experts on GPU). The move from `--n-cpu-moe 32` to 35 traded a little GPU-expert speed for OOM safety after high-load sessions OOM'd at 32 and 33. If headroom proves too thin for production bursts, dial back `--n-cpu-moe` to 37 (only 3 layers on GPU, ~0.9 GiB more headroom) by editing `scripts/frank-default-small.env`.
- 24 GB VRAM is close to saturated with this config. At idle ~23.0 GB used, leaving an estimated **~1.0 GiB** headroom at `--n-cpu-moe 32` (8 layers' experts on GPU) with `ubatch 1024`. A llama-bench sweep ([[frank-default-small-benchmark]]) chose this state: it maximises decode (~48.7 t/s) while staying above the OOM boundary that `ncmoe 32 - ubatch 2048` crossed (24.4 GiB). If headroom proves too thin for production bursts, reduce `ubatch` to 768 (~1.3 GiB headroom) or dial `--n-cpu-moe` back to 34 at `ubatch 1536` (~2.0 GiB headroom) by editing `scripts/frank-default-small.env`.
- 62 GB system RAM holds the ~29 GB of MoE expert weights with room to spare (~57 GB available after load).
- 127 GB swap is available for CPU KV cache paging if GPU KV offload is disabled.
- Root disk has approximately 140 GB free. Store the GGUF models under `/home/dank/models` (about 32 GB total).
+1 -1
View File
@@ -143,7 +143,7 @@ The active service on Dankclaw runs llama.cpp serving the HauhauCS Qwen3.6-27B u
### Dankserver — frank-default-small
The active service on Dankserver runs llama.cpp (upstream, `b10108+`) and serves the HauhauCS Qwen3.6-35B-A3B uncensored `Q6_K_P` model under the alias `frank-default-small` on port 7770. It uses **ngram-mod** speculative decoding (`--spec-ngram-mod-n-min 48 / n_max 64 / n_match 24`), **4 parallel slots** at 200000 context each (pool 800000), and mmproj vision. **35 of 40 MoE expert layers** stay on CPU (`--n-cpu-moe 35`); 5 expert layers' weights are back on GPU alongside all non-expert tensors (`--gpu-layers all`). KV stays on GPU (K=`q8_0`, V=`f16`). Batch 8192 / ubatch 2048, `--ctx-checkpoints 4`, `--no-mmap`. The unit file is `scripts/frank-default-small.service`, symlinked to `/etc/systemd/system/`. It launches through `scripts/serve-llama-frank-small.sh`, which reads tunables from `scripts/frank-default-small.env`.
The active service on Dankserver runs llama.cpp (upstream, `b10108+`) and serves the HauhauCS Qwen3.6-35B-A3B uncensored `Q6_K_P` model under the alias `frank-default-small` on port 7770. It uses **ngram-mod** speculative decoding (`--spec-ngram-mod-n-min 48 / n_max 64 / n_match 24`), **4 parallel slots** at 200000 context each (pool 800000), and mmproj vision. **32 of 40 MoE expert layers** stay on CPU (`--n-cpu-moe 32`); 8 expert layers' weights are back on GPU alongside all non-expert tensors (`--gpu-layers all`). KV stays on GPU (K=`q8_0`, V=`f16`). Batch 8192 / ubatch 1024, `--ctx-checkpoints 4`, `--no-mmap`. The unit file is `scripts/frank-default-small.service`, symlinked to `/etc/systemd/system/`. It launches through `scripts/serve-llama-frank-small.sh`, which reads tunables from `scripts/frank-default-small.env`.
> Note: this service replaced the retired `vllm-awq-qwen36` (AWQ 4-bit, port 34401) and the earlier `vllm-qwen36` (FP8) / `llama-server` (ROCmFPX) units. The repo tracks `main` on Dankserver at `/home/dank/vLLM`.
+129
View File
@@ -0,0 +1,129 @@
---
type: reference
title: frank-default-small Benchmark — ncmoe and Batch Tuning
description: llama-bench sweep of MoE CPU offload (ncmoe) and batch/ubatch on the RTX 3090 for Qwen3.6-35B-A3B Q6_K_P.
tags:
- benchmark
- llamacpp
- ncmoe
- ubatch
- dankserver
---
# frank-default-small Benchmark — ncmoe and Batch/Ubatch Tuning
This page records a llama-bench sweep on Dankserver (RTX 3090, 24 GiB) for
the HauhauCS Qwen3.6-35B-A3B Q6_K_P model. The sweep decided the final
`--n-cpu-moe` and `--ubatch-size` values for `frank-default-small`.
Run date: 2026-08-13. Build: llama.cpp `555881ebc` (10121). CUDA, 7 threads,
`--cache-type-k q8_0 --cache-type-v f16`, `--fit-target 0` (KV auto-sized to
fill VRAM). Prompt 16384 tokens, generation 512 tokens, 2 repetitions.
## Headline Findings
### Generation does not depend on batch or ubatch
For every `ncmoe` value, generation throughput stayed flat across all
`ubatch` values from 256 to 4096. The delta between the lowest and highest
was under one token per second. Generation depends only on how many MoE
expert layers stay on the GPU as `ncmoe` gets smaller.
| `ncmoe` | Expert layers on GPU | Generation (t/s) |
| ------- | -------------------- | ---------------- |
| 40 | 0 | 40.9 |
| 38 | 2 | 42.6 |
| 36 | 4 | 44.4 |
| 35 | 5 | 45.5 |
| 34 | 6 | 46.4 |
| 32 | 8 | 48.7 |
| 30 | 10 | 51.1 |
Each pair of expert layers moved to the GPU adds roughly 1.1-2.0 t/s of
generation. Moving from `ncmoe 35` to `ncmoe 32` adds about 3.2 t/s, or 7
percent.
### Prefill and graph memory scale with ubatch
Prefill throughput climbs with `ubatch` because a prompt splits into
`prompt / ubatch` micro-batches. For `ncmoe 35` at 16384 prompt tokens:
| `ubatch` | Prefill (t/s) | Peak graph VRAM (MiB) |
| -------- | ------------- | --------------------- |
| 256 | 245 | 6838 |
| 512 | 416 | 6852 |
| 768 | 556 | 7074 |
| 1024 | 710 | 7330 |
| 1536 | 895 | 7846 |
| 2048 | 1188 | 8574 |
The logical `--batch-size` does not matter. At a fixed `ubatch`, `batch`
values of 2048, 4096, and 8192 gave identical prefill speed and peak VRAM.
## Peak VRAM by ncmoe and ubatch
Peak VRAM (llama-bench, single context) rises both when `ncmoe` drops
(more experts on GPU) and when `ubatch` rises (bigger compute graph):
| `ncmoe` | ub 512 | ub 1024 | ub 1536 | ub 2048 |
| ------- | ------ | ------- | ------- | ------- |
| 38 | 4590 | 5068 | 5584 | 6086 |
| 36 | 6098 | 6576 | 7092 | 7594 |
| 35 | 6852 | 7330 | 7846 | 8574 |
| 34 | 7606 | 8084 | 8600 | 9102 |
| 32 | 9114 | 9592 | 10108 | 10610 |
| 30 | 10622 | 11100 | 11616 | 12118 |
## VRAM Budget Model
The live service holds a fixed 800000-token KV pool plus the mmproj vision
tower plus CUDA overhead. The model below fits llama-bench peak VRAM into a
24 GiB budget:
```
service VRAM = llama-bench peak + KV pool (11.44 GiB) + overhead (2.2 GiB)
```
This model reproduces the historical OOMs. Configurations whose sum exceeds
24 GiB fail. For example, `ncmoe 32 - ubatch 2048` sums to about 24.4 GiB
and fails, which matches the recorded OOMs at `ncmoe 32` and `33`.
## Candidate Configurations
| Configuration | Gen (t/s) | Prefill (t/s) | Headroom (MiB) | Fit |
| ------------------ | --------- | ------------- | -------------- | --- |
| ncmoe 35, ub 2048 | 45.5 | 1188 | 2035 | OK |
| ncmoe 34, ub 2048 | 46.4 | 1221 | 1507 | OK |
| ncmoe 34, ub 1536 | 46.5 | 914 | 2009 | OK |
| ncmoe 32, ub 1024 | 48.7 | 766 | 1017 | OK |
| ncmoe 32, ub 768 | 48.8 | 600 | 1273 | OK |
| ncmoe 30, ub 1536 | 51.2 | 1009 | under | OOM |
## Chosen State
The chosen state balances generation speed against prefill speed and OOM
headroom:
```
--n-cpu-moe 32 # 8 expert layers on GPU
--batch-size 8192
--ubatch-size 1024
```
This gives generation about 48.7 t/s (7 percent above the previous
`ncmoe 35`) while keeping the box above the OOM boundary. If prefill speed
matters more than generation, use `ncmoe 34 - ubatch 2048`. If stability
headroom matters most, use `ncmoe 34 - ubatch 1536`.
## Limitations
llama-bench measures raw decode and prefill. It does not run speculative
decoding, parallel slots, or the mmproj vision tower. The live service adds
those on top. The VRAM model uses a fixed 2.2 GiB overhead estimate; the
real overhead varies a little with load.
## See Also
- [[Dankserver System Specs]]
- [[deployment]]
- [[DFlash DSpark Speculative Decoding]]
+1
View File
@@ -52,6 +52,7 @@ DFlash draft, port 7770]
- [[Running Qwen3.6 35B A3B FP8 on Dankserver]] — MoE model (35B total, 3B active) on RTX 3090
- [[Running Qwen3.6 27B FP8 on Dankclaw]] — Dense model (27B) on Strix Halo APU
- [[frank-default-large-benchmark]] — backend/spec benchmark that drove the Dankclaw llama.cpp deployment
- [[frank-default-small-benchmark]] — ncmoe and batch/ubatch sweep that drove the Dankserver state
- [[Dankclaw Improvements]] — researched enhancements: self-hosted agentic tools, runtime tuning, server/OS settings
## Speculative Decoding & Quantization
+10 -6
View File
@@ -8,15 +8,17 @@ PORT=7770
# (Increased from 3×200k to add a 4th parallel stream.)
CTX_SIZE=800000
PARALLEL=4
# Spec: ngram-mod. n_min=48, n_max=64, n_match=24 (defaults). 5 expert
# layers back on GPU; 35 on CPU. Batch 8192 / ubatch 2048.
# Spec: ngram-mod. n_min=48, n_max=64, n_match=24 (defaults). 8 expert
# layers back on GPU; 32 on CPU. Batch 8192 / ubatch 1024.
SPEC_TYPE=ngram-mod
NGRAM_MOD_N_MIN=48
NGRAM_MOD_N_MAX=64
NGRAM_MOD_N_MATCH=24
# Expert offload: 35 of 40 layers keep MoE weights on CPU; remaining
# 5 layers have their expert weights resident on GPU for faster routing.
N_CPU_MOE=35
# Expert offload: 32 of 40 layers keep MoE weights on CPU; remaining
# 8 layers have their expert weights resident on GPU for faster routing.
# Benchmark-chosen (see frank-default-small-benchmark.md): max decode at
# the headroom that stays above the historical OOM boundary.
N_CPU_MOE=32
N_GPU_LAYERS=all
# KV cache on GPU, K quantized to q8_0, V stays f16 (user-locked decision).
CACHE_TYPE_K=q8_0
@@ -25,8 +27,10 @@ CACHE_TYPE_V=f16
# larger batch/ubatch (leaves headroom for ctx-checkpoints operation).
CTX_CHECKPOINTS=4
# Larger batches / ubatch for big prefill workloads.
# ubatch 1024 (benchmark-chosen): decode is flat vs ubatch; 1024 frees
# compute-graph VRAM to afford ncmoe 32 while keeping prefill ~766 t/s.
BATCH_SIZE=8192
UBATCH_SIZE=2048
UBATCH_SIZE=1024
# Load the model into RAM rather than lazy-mapping it. The MoE experts live on
# CPU, so eager RAM load avoids page faults during decode (uses ~31GB RAM).
NO_MMAP=1
+2 -2
View File
@@ -32,10 +32,10 @@ fi
: "${NGRAM_MOD_N_MATCH:=24}"
: "${CACHE_TYPE_K:=q8_0}"
: "${CACHE_TYPE_V:=f16}"
: "${N_CPU_MOE:=35}" # 35 of 40 layers: MoE expert weights stay on CPU; 5 on GPU
: "${N_CPU_MOE:=32}" # 32 of 40 layers: MoE expert weights stay on CPU; 8 on GPU
: "${N_GPU_LAYERS:=all}" # every non-expert tensor goes to GPU
: "${BATCH_SIZE:=2048}"
: "${UBATCH_SIZE:=512}"
: "${UBATCH_SIZE:=1024}"
: "${CTX_CHECKPOINTS:=0}"
: "${NO_MMAP:=0}"
: "${TEMPERATURE:=1.0}"