Qwen3.8-27B · GGUF IQ3_S · llama.cpp

Qwen3.8-27B GSQ IQ3_S GGUF on llama.cpp, 44.9 t/s warm, same model as EXL3 runs but 6.3× slower prefill.

44.9
WARM DECODE (T/S)
30.1
COLD DECODE (T/S)
23.45
WARM TTFT (S)
85.70
COLD TTFT (S)
20.9
PEAK VRAM (GB)
1
CONCURRENT REQS
llm-servingllamacppggufb70ASRock B70baseline

Based on: https://huggingface.co/Greatjedi/Qwen3.8-27B-Intel-Arc-Tuned-GGUF

Third engine in the journal: llama.cpp on the same ASROCK B70 (card2/renderD129), same model family as runs #2/#3 (Qwen3.8-27B) but GGUF quant (IQ3_S GSQ "Intel Arc Tuned") with an embedded MTP draft head (Q4_K). Dual speculative decoding: ngram-mod + draft-mtp.

Status: awaiting launch, blocker: b70-exl3 currently holds port 9932 AND card2; stop it first.

Config

Field Value
Model Greatjedi/Qwen3.8-27B-Intel-Arc-Tuned-GGUF → /models/Qwen3.8-27B-GSQ-RCO-IQ3_S-Intel-Arc-Tuned-MTP-Q4_K.gguf (IQ3_S ≈3.5 bpw, MTP draft head Q4_K embedded)
Inference platform llama.cpp ghcr.io/ggml-org/llama.cpp:full-intel, SYCL/Level-Zero backend, single B70 (SYCL_DEVICE_FILTER=level_zero:0)
GPU env GGML_SYCL_ENABLE_GRAPH=1, GGML_SYCL_F16=1, GGML_SYCL_ENABLE_COPY=1, ZES_ENABLE_SYSMAN=1, SYCL_USE_XMX=1, ZE_AFFINITY_MASK=0; SYCL_CACHE_PERSISTENT=0 (recompiles every start)
Port / host your-LAN-IP:9932
Context --ctx-size 163840 (alternatives tried per comments: 262144/204256/196608/180000/131072)
Layers --n-gpu-layers all, --fit-target 256 (256 MiB margin/device for auto-fit)
Flash attn on
KV cache --cache-type-k q4_0 --cache-type-v q4_0, --kv-unified --kv-offload (offload default-on, watch startup log for the actual split)
Speculative decoding --spec-type ngram-mod,draft-mtp: ngram-mod n-match 24, n-min 1, n-max 3; draft-mtp n-max 3, p-min 0.5
Prefill batching --batch-size 16384 --ubatch-size 2048
CPU --threads 8 --threads-batch 12 (7900X = 12C); OMP_NUM_THREADS=12
Prompt caching --cache-prompt --cache-reuse 2048 --cache-ram 2048 (disk prompt cache, 2 GiB RAM budget, reuse chunks ≥2048 tokens via KV shifting)
Concurrency --parallel 1, --n-predict -1
Sampling defaults temp 0.7, top-p 0.9, top-k 40, repeat-penalty 1.05 (last-n 256), presence 0.0, dry-penalty last-n 512
Reasoning / tools --reasoning on; tools: read_file, file_glob_search, grep_search, write_file, edit_file, get_info; --jinja + /models/qwen-sharp.jinja (from the model repo's chat_templates/) template; alias Qwen3.8-27B
Monitoring --metrics --slots --warmup --perf

Benchmark protocol note: server sampling defaults (temp 0.7, penalties) differ from runs #1–#3. For comparability, the client request overrides to greedy-equivalent: temperature=0, top_p=1.0, top_k=1, repeat_penalty=1.0, presence_penalty=0.0. Prompt + question identical (64,388 corpus tokens).

Startup stats

Stats

Metric Cold (req #1) Warm (APC hit)
Prompt tokens 64,501 64,501
TTFT (s) client 85.74 / server prompt eval 63.64 s client 23.45 / server prompt eval 0.35 s (only 4 tokens re-prefilled)
Prefill (tok/s) 1,013.59 (server; no JIT warnings in log, real speed, not an artifact) cache-served (cached_tokens 64,497/64,501)
Decode (tok/s, generated) client 30.1 (1,026 tok / 34.14 s); server 22.81 incl. spec overhead client 44.9 (1,406 tok / 31.30 s); server 25.87 incl. spec overhead
Completion tokens 1,026 1,406
E2E (s) 119.88 (client) / 108.57 (server total) 54.75 (client) / 54.67 (server total)
VRAM (GB) 20.4 at start (user) 20.9 peak (user)
Spec decode draft accept 0.693 (580/837), mean len 2.61 draft accept 0.759 (869/1145), mean len 2.87; cumulative 73.1 %

Baselines to compare (same corpus): vLLM MoE run #1 warm decode 105.8 tok/s; EXL3 runs #2/#3 warm decode ~57 tok/s, prefill ~6,439 tok/s.

Findings

Recommendations

Quality variant

  1. KV dtype q4_0 → f16/bf16 (--cache-type-k/v), quantized KV is the main long-context recall tax; ~2× KV VRAM (~+3–4 GiB at 163k, still fits in 32 GB).
  2. Higher-quant GGUF (IQ4_XS/IQ5) if IQ3_S quality disappoints, fits with room on one B70.
  3. Draft KV already f16 (default), leave it.

Speed variant

  1. ubatch-size 2048 → 4096, prefill is the headline weakness (1,014 tok/s vs ~6,439 on other engines); bigger chunks are the first lever.
  2. --no-kv-offload A/B, offload is default-on; if KV writes are crossing PCIe during prefill, disabling it (everything fits on GPU) could close most of the prefill gap.
  3. ctx-size 163840 → 262144, headroom confirmed: only +0.5 GB VRAM for 65k tokens of q4_0 KV (~8 B/token), so 262k ctx costs ~+2 GiB. No wall in sight.
  4. SYCL_CACHE_PERSISTENT=0 → 1, sycl host volume already mapped but persistence off; recompiles every start. A/B after baseline.
  5. Spec decode isolation, ngram-mod and draft-mtp both on (acceptance 69–76 %); A/B each alone to see net gain per type. --spec-draft-p-min 0.5 is conservative.
  6. Follow-up: SSE first-token delay, constant ~22–23 s gap between server prompt-eval completion and client TTFT on both requests; verify with curl -N raw timing before trusting llama.cpp TTFT numbers.

Appendix: docker-compose (verbatim, as provided 2026-10-21)

services:
  llamacpp:
    container_name: b70
    image: ghcr.io/ggml-org/llama.cpp:full-intel
    restart: unless-stopped
    ports:
      - "9932:9932"
    volumes:
      - ./models:/models
      - ./cache/llamacpp:/root/.cache/llamacpp:Z
      - ./cache/sycl:/root/.cache/sycl:Z
      - ./cache/huggingface:/root/.cache/huggingface:Z
    devices:
      - /dev/dri
    group_add:
      - "992"
    environment:
      GGML_SYCL_ENABLE_GRAPH: 1
      UR_LOADER_USE_LEVEL_ZERO_V2: 0
      ZE_AFFINITY_MASK: 0
      SYCL_DEVICE_FILTER: level_zero:0
      ONEAPI_DEVICE_SELECTOR: level_zero:0
      SYCL_PI_LEVEL_ZERO_USE_IMMEDIATE_COMMANDLISTS: "1"
      GGML_SYCL_ENABLE_COPY: "1"
      GGML_SYCL_F16: "1"
      ZES_ENABLE_SYSMAN: "1"
      OMP_NUM_THREADS: "12"
      HF_HOME: /root/.cache/huggingface
      HUGGINGFACE_HUB_CACHE: /root/.cache/huggingface
      LLAMA_CPP_CACHE: /root/.cache/llamacpp
      SYCL_CACHE_PERSISTENT: "0"
      SYCL_CACHE_PATH: /root/.cache/sycl
      SYCL_USE_XMX: 1
    command:
      - --server
      - --model
      - /models/Qwen3.8-27B-GSQ-RCO-IQ3_S-Intel-Arc-Tuned-MTP-Q4_K.gguf
      - --spec-type 
      - "ngram-mod,draft-mtp"
      - --spec-ngram-mod-n-match 
      - "24"
      - --spec-ngram-mod-n-min
      - "1"
      - --spec-ngram-mod-n-max
      - "3"
      - --spec-draft-n-max
      - "3"
      - --spec-draft-p-min
      - "0.5" 
      - --jinja 
      - --chat-template-file 
      - /models/qwen-sharp.jinja
      - --alias 
      - "Qwen3.8-27B"
      - --host
      - 0.0.0.0
      - --port
      - "9932"
      - --n-gpu-layers
      - "all"
      - --flash-attn
      - "on"
      - --fit-target
      - "256"
      - --ctx-size
      - "163840"
      - --n-predict 
      - "-1"
      - --temp 
      - "0.7"
      - --top-p 
      - "0.9"
      - --top-k 
      - "40"
      - --repeat-penalty
      - "1.05"
      - --repeat-last-n
      - "256"
      - --presence-penalty
      - "0.0"
      - --dry-penalty-last-n
      - "512"
      - --threads
      - "8"
      - --threads-batch
      - "12"
      - --batch-size
      - "16384"
      - --ubatch-size
      - "2048"
      - --cors-origins
      - "*"
      - --cache-type-k
      - "q4_0"
      - --cache-type-v
      - "q4_0"
      - --cache-prompt
      - --cache-reuse
      - "2048"
      - --cache-ram
      - "2048"
      - --parallel
      - "1"
      - --kv-unified
      - --kv-offload
      - --reasoning
      - "on"
      - --tools
      - "read_file,file_glob_search,grep_search,write_file,edit_file,get_info"
      - --metrics
      - --slots
      - --warmup
      - --perf
RELATED
2026-10-17 · llama.cpp SYCL/XPU · 1x B70 · ctx 163840