Instructions to use HelloSun/flint_cpu_opt with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use HelloSun/flint_cpu_opt with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf HelloSun/flint_cpu_opt:UD-Q4_K_XL # Run inference directly in the terminal: llama cli -hf HelloSun/flint_cpu_opt:UD-Q4_K_XL
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf HelloSun/flint_cpu_opt:UD-Q4_K_XL # Run inference directly in the terminal: llama cli -hf HelloSun/flint_cpu_opt:UD-Q4_K_XL
Build from source code
git clone https://github.com/ggml-org/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-app # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama serve -hf HelloSun/flint_cpu_opt:UD-Q4_K_XL # Run inference directly in the terminal: ./build/bin/llama cli -hf HelloSun/flint_cpu_opt:UD-Q4_K_XL
Use Docker
docker model run hf.co/HelloSun/flint_cpu_opt:UD-Q4_K_XL
- Llama new
- LM Studio
- Jan
- vLLM
How to use HelloSun/flint_cpu_opt with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "HelloSun/flint_cpu_opt" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "HelloSun/flint_cpu_opt", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/HelloSun/flint_cpu_opt:UD-Q4_K_XL
- Ollama
How to use HelloSun/flint_cpu_opt with Ollama:
ollama run hf.co/HelloSun/flint_cpu_opt:UD-Q4_K_XL
- Unsloth Desktop
- Pi
How to use HelloSun/flint_cpu_opt with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf HelloSun/flint_cpu_opt:UD-Q4_K_XL
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "HelloSun/flint_cpu_opt:UD-Q4_K_XL" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Docker Model Runner
How to use HelloSun/flint_cpu_opt with Docker Model Runner:
docker model run hf.co/HelloSun/flint_cpu_opt:UD-Q4_K_XL
- Lemonade
How to use HelloSun/flint_cpu_opt with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull HelloSun/flint_cpu_opt:UD-Q4_K_XL
Run and chat with the model
lemonade run user.flint_cpu_opt-UD-Q4_K_XL
List all available models
lemonade list
- Hermes Agent
How to use HelloSun/flint_cpu_opt with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf HelloSun/flint_cpu_opt:UD-Q4_K_XL
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default HelloSun/flint_cpu_opt:UD-Q4_K_XL
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use HelloSun/flint_cpu_opt with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf HelloSun/flint_cpu_opt:UD-Q4_K_XL
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "HelloSun/flint_cpu_opt:UD-Q4_K_XL" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
flint CPU opt: IQ4_XS AVX512-VNNI vec_dot, Q5_K mask merge, rebased on de5122d; re-measured benchmarks and KLD
Browse files- README.md +9 -9
- benchmarks/ab-interleaved-flint.csv +27 -0
- benchmarks/kld-bisect.log +5 -0
- benchmarks/kld_vs_stock.log +17 -0
- benchmarks/profile-decode.txt +55 -0
- benchmarks/profile-prefill.txt +79 -0
- benchmarks/summary.md +38 -10
- build.sh +7 -2
- machine.txt +5 -6
- patches/BASE_COMMIT +1 -1
- patches/flint-cpu-opt.patch +491 -78
- patches/optional-profiler.patch +1 -1
README.md
CHANGED
|
@@ -1,15 +1,15 @@
|
|
| 1 |
# flint CPU optimization
|
| 2 |
|
| 3 |
-
|
|
|
|
|
|
|
| 4 |
|
| 5 |
-
|
| 6 |
-
```bash
|
| 7 |
-
git clone https://github.com/ggerganov/llama.cpp
|
| 8 |
-
cd llama.cpp
|
| 9 |
-
git checkout $(cat patches/BASE_COMMIT)
|
| 10 |
-
git apply patches/flint-cpu-opt.patch
|
| 11 |
./build.sh
|
|
|
|
| 12 |
```
|
| 13 |
|
| 14 |
-
|
| 15 |
-
|
|
|
|
|
|
|
|
|
| 1 |
# flint CPU optimization
|
| 2 |
|
| 3 |
+
`flint-UD-Q4_K_XL.gguf` is the unmodified file from [unsloth/flint-GGUF](https://huggingface.co/unsloth/flint-GGUF).
|
| 4 |
+
All changes are in `patches/flint-cpu-opt.patch` (llama.cpp commit in `patches/BASE_COMMIT`), in the style of
|
| 5 |
+
[HelloSun/Qwen3.6-35B-A3B-GGUF_CPU_OPT](https://huggingface.co/HelloSun/Qwen3.6-35B-A3B-GGUF_CPU_OPT).
|
| 6 |
|
| 7 |
+
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
./build.sh
|
| 9 |
+
taskset -c 0-15 llama.cpp/build/bin/llama-cli -m flint-UD-Q4_K_XL.gguf -t 16 -fa on -lm mlock
|
| 10 |
```
|
| 11 |
|
| 12 |
+
Measured on Xeon Platinum 8559C, 16 threads (median of 3 interleaved rounds, vs stock llama.cpp):
|
| 13 |
+
pp256 231 -> 296 t/s (1.28x), pp2048 274 -> 307 (1.12x), tg128 38.2 -> 42.8 (1.12x).
|
| 14 |
+
PPL 18.28 vs 18.36 stock (no degradation), but **KLD vs stock is 0.067** (top-1 agreement ~92 %), much larger than on Qwen3.6.
|
| 15 |
+
Details, caveats and the KLD bisect: `benchmarks/summary.md`. Validated only on this CPU.
|
benchmarks/ab-interleaved-flint.csv
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
stock,1,0,245.145577
|
| 2 |
+
stock,1,0,268.315708
|
| 3 |
+
stock,1,0,37.025341
|
| 4 |
+
qwen,1,0,264.423995
|
| 5 |
+
qwen,1,0,307.766206
|
| 6 |
+
qwen,1,0,42.127365
|
| 7 |
+
opt,1,0,274.398648
|
| 8 |
+
opt,1,0,306.705280
|
| 9 |
+
opt,1,0,43.836806
|
| 10 |
+
stock,2,0,229.210797
|
| 11 |
+
stock,2,0,276.811500
|
| 12 |
+
stock,2,0,38.154299
|
| 13 |
+
qwen,2,0,265.295236
|
| 14 |
+
qwen,2,0,308.702421
|
| 15 |
+
qwen,2,0,42.523910
|
| 16 |
+
opt,2,0,295.754988
|
| 17 |
+
opt,2,0,301.992873
|
| 18 |
+
opt,2,0,42.808636
|
| 19 |
+
stock,3,0,231.043869
|
| 20 |
+
stock,3,0,274.222148
|
| 21 |
+
stock,3,0,39.321185
|
| 22 |
+
qwen,3,0,261.775600
|
| 23 |
+
qwen,3,0,304.829067
|
| 24 |
+
qwen,3,0,39.530870
|
| 25 |
+
opt,3,0,299.816432
|
| 26 |
+
opt,3,0,318.658592
|
| 27 |
+
opt,3,0,41.833254
|
benchmarks/kld-bisect.log
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
no-VNNI Q4K : Mean KLD: 0.067003 ± 0.005035
|
| 2 |
+
no-VNNI Q5K : Mean KLD: 0.052438 ± 0.003954
|
| 3 |
+
no-VNNI Q6K : Mean KLD: 0.068454 ± 0.005053
|
| 4 |
+
no-VNNI IQ4XS : Mean KLD: 0.066395 ± 0.004854
|
| 5 |
+
ALLDONE
|
benchmarks/kld_vs_stock.log
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
== base (stock)
|
| 2 |
+
1.31.737.501 I Final estimate: PPL = 18.3627 +/- 0.79499
|
| 3 |
+
== opt vs stock
|
| 4 |
+
0.13.393.993 I
|
| 5 |
+
chunk PPL ln(PPL(Q)/PPL(base)) KL Divergence Δp RMS Same top p
|
| 6 |
+
6 24.3841 ± 2.5972 0.06191 ± 0.02147 0.06779 ± 0.00974 4.503 ± 0.393 % 91.699 ± 0.706 %
|
| 7 |
+
19 23.9972 ± 1.4052 0.03615 ± 0.00982 0.06924 ± 0.00674 4.672 ± 0.267 % 91.889 ± 0.392 %
|
| 8 |
+
27 17.8997 ± 0.8389 0.02832 ± 0.00775 0.06868 ± 0.00558 5.388 ± 0.294 % 92.433 ± 0.319 %
|
| 9 |
+
Mean PPL(Q) : 18.277320 ± 0.787208
|
| 10 |
+
Mean PPL(base) : 17.797758 ± 0.744380
|
| 11 |
+
Cor(ln(PPL(Q)), ln(PPL(base))): 98.68%
|
| 12 |
+
Mean ln(PPL(Q)/PPL(base)) : 0.026588 ± 0.007011
|
| 13 |
+
Mean PPL(Q)/PPL(base) : 1.026945 ± 0.007200
|
| 14 |
+
Mean PPL(Q)-PPL(base) : 0.479562 ± 0.131595
|
| 15 |
+
Mean KLD: 0.066583 ± 0.004897
|
| 16 |
+
99.9% KLD: 7.426280
|
| 17 |
+
99.0% KLD: 1.112220
|
benchmarks/profile-decode.txt
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
| model | size | params | backend | threads | fa | lm | test | t/s |
|
| 2 |
+
| ------------------------------ | ---------: | ---------: | ---------- | ------: | --: | ---------: | --------------: | -------------------: |
|
| 3 |
+
| flint ?B Q4_K - Medium | 23.33 GiB | 39.79 B | CPU | 16 | 1 | mlock | tg64 | 37.72 ± 0.00 |
|
| 4 |
+
|
| 5 |
+
[GGML_PROF] total_us=1678629
|
| 6 |
+
[GGML_PROF] GET_ROWS f32 <q8_0 [ 2048, 1, 1] 0.45 ms 0.03% calls=65 us/call=6.9
|
| 7 |
+
[GGML_PROF] RMS_NORM f32 <f32 [ 2048, 1, 1] 18.00 ms 1.07% calls=6435 us/call=2.8
|
| 8 |
+
[GGML_PROF] MUL_MAT f32 <q8_0 [ 4096, 1, 1] 171.92 ms 10.24% calls=2730 us/call=63.0
|
| 9 |
+
[GGML_PROF] RMS_NORM f32 <f32 [ 128, 32, 1] 6.32 ms 0.38% calls=3185 us/call=2.0
|
| 10 |
+
[GGML_PROF] MUL_MAT f32 <q8_0 [ 512, 1, 1] 62.51 ms 3.72% calls=5460 us/call=11.4
|
| 11 |
+
[GGML_PROF] RMS_NORM f32 <f32 [ 128, 4, 1] 7.42 ms 0.44% calls=3185 us/call=2.3
|
| 12 |
+
[GGML_PROF] SET_ROWS f16 <f32 [ 512, 256, 1] 7.33 ms 0.44% calls=6370 us/call=1.2
|
| 13 |
+
[GGML_PROF] FLASH_ATTN_EXT f32 <f32 [ 128, 32, 1] 29.72 ms 1.77% calls=3185 us/call=9.3
|
| 14 |
+
[GGML_PROF] MUL_MAT f32 <q8_0 [ 2048, 1, 1] 218.00 ms 12.99% calls=5070 us/call=43.0
|
| 15 |
+
[GGML_PROF] ADD f32 <f32 [ 2048, 1, 1] 34.85 ms 2.08% calls=24700 us/call=1.4
|
| 16 |
+
[GGML_PROF] MUL_MAT f32 <q8_0 [ 6144, 1, 1] 22.79 ms 1.36% calls=260 us/call=87.6
|
| 17 |
+
[GGML_PROF] GLU f32 <f32 [ 6144, 1, 1] 0.63 ms 0.04% calls=130 us/call=4.8
|
| 18 |
+
[GGML_PROF] ROPE f32 <f32 [ 128, 32, 1] 5.86 ms 0.35% calls=2275 us/call=2.6
|
| 19 |
+
[GGML_PROF] ROPE f32 <f32 [ 128, 4, 1] 2.98 ms 0.18% calls=2275 us/call=1.3
|
| 20 |
+
[GGML_PROF] MUL_MAT f32 <bf16 [ 256, 1, 1] 43.35 ms 2.58% calls=3055 us/call=14.2
|
| 21 |
+
[GGML_PROF] UNARY f32 <f32 [ 256, 1, 1] 4.08 ms 0.24% calls=3055 us/call=1.3
|
| 22 |
+
[GGML_PROF] ARGSORT i32 <f32 [ 256, 1, 1] 36.86 ms 2.20% calls=3055 us/call=12.1
|
| 23 |
+
[GGML_PROF] GET_ROWS f32 <f32 [ 1, 6, 1] 4.56 ms 0.27% calls=3055 us/call=1.5
|
| 24 |
+
[GGML_PROF] SUM_ROWS f32 <f32 [ 1, 1, 1] 3.27 ms 0.19% calls=3055 us/call=1.1
|
| 25 |
+
[GGML_PROF] CLAMP f32 <f32 [ 1, 1, 1] 3.43 ms 0.20% calls=3055 us/call=1.1
|
| 26 |
+
[GGML_PROF] DIV f32 <f32 [ 6, 1, 1] 3.41 ms 0.20% calls=3055 us/call=1.1
|
| 27 |
+
[GGML_PROF] MUL_MAT_ID f32 <iq3_s [ 512, 6, 1] 18.62 ms 1.11% calls=130 us/call=143.2
|
| 28 |
+
[GGML_PROF] GLU f32 <f32 [ 512, 6, 1] 4.30 ms 0.26% calls=3055 us/call=1.4
|
| 29 |
+
[GGML_PROF] UNARY f32 <f32 [ 512, 6, 1] 3.62 ms 0.22% calls=3055 us/call=1.2
|
| 30 |
+
[GGML_PROF] POOL_1D f32 <f32 [ 1, 6, 1] 13.12 ms 0.78% calls=3055 us/call=4.3
|
| 31 |
+
[GGML_PROF] SCALE f32 <f32 [ 1, 6, 1] 10.41 ms 0.62% calls=9165 us/call=1.1
|
| 32 |
+
[GGML_PROF] LOG f32 <f32 [ 1, 6, 1] 3.64 ms 0.22% calls=3055 us/call=1.2
|
| 33 |
+
[GGML_PROF] UNARY f32 <f32 [ 1, 6, 1] 7.11 ms 0.42% calls=6110 us/call=1.2
|
| 34 |
+
[GGML_PROF] CLAMP f32 <f32 [ 1, 6, 1] 3.29 ms 0.20% calls=3055 us/call=1.1
|
| 35 |
+
[GGML_PROF] DIV f32 <f32 [ 512, 6, 1] 5.20 ms 0.31% calls=3055 us/call=1.7
|
| 36 |
+
[GGML_PROF] MUL_MAT_ID f32 <q5_K [ 2048, 6, 1] 141.87 ms 8.45% calls=1885 us/call=75.3
|
| 37 |
+
[GGML_PROF] MUL f32 <f32 [ 2048, 6, 1] 30.55 ms 1.82% calls=6110 us/call=5.0
|
| 38 |
+
[GGML_PROF] MUL_MAT f32 <q8_0 [ 1024, 1, 1] 82.51 ms 4.92% calls=4420 us/call=18.7
|
| 39 |
+
[GGML_PROF] GLU f32 <f32 [ 1024, 1, 1] 3.47 ms 0.21% calls=3055 us/call=1.1
|
| 40 |
+
[GGML_PROF] MUL_MAT_ID f32 <q5_K [ 512, 6, 1] 220.48 ms 13.13% calls=2340 us/call=94.2
|
| 41 |
+
[GGML_PROF] MUL_MAT_ID f32 <q8_0 [ 2048, 6, 1] 12.57 ms 0.75% calls=65 us/call=193.4
|
| 42 |
+
[GGML_PROF] MUL_MAT_ID f32 <q6_K [ 2048, 6, 1] 10.04 ms 0.60% calls=65 us/call=154.5
|
| 43 |
+
[GGML_PROF] MUL_MAT f32 <q5_K [ 4096, 1, 1] 33.90 ms 2.02% calls=455 us/call=74.5
|
| 44 |
+
[GGML_PROF] MUL_MAT f32 <q5_K [ 512, 1, 1] 18.08 ms 1.08% calls=910 us/call=19.9
|
| 45 |
+
[GGML_PROF] MUL_MAT f32 <q5_K [ 2048, 1, 1] 52.65 ms 3.14% calls=1235 us/call=42.6
|
| 46 |
+
[GGML_PROF] MUL_MAT_ID f32 <iq4_xs [ 512, 6, 1] 102.81 ms 6.12% calls=3250 us/call=31.6
|
| 47 |
+
[GGML_PROF] MUL_MAT_ID f32 <iq4_xs [ 2048, 6, 1] 35.32 ms 2.10% calls=1040 us/call=34.0
|
| 48 |
+
[GGML_PROF] MUL_MAT_ID f32 <q4_K [ 512, 6, 1] 12.47 ms 0.74% calls=390 us/call=32.0
|
| 49 |
+
[GGML_PROF] MUL_MAT f32 <q5_K [ 1024, 1, 1] 36.01 ms 2.14% calls=1560 us/call=23.1
|
| 50 |
+
[GGML_PROF] MUL_MAT f32 <iq4_xs [ 1024, 1, 1] 2.38 ms 0.14% calls=130 us/call=18.3
|
| 51 |
+
[GGML_PROF] MUL_MAT f32 <iq4_xs [ 2048, 1, 1] 1.02 ms 0.06% calls=65 us/call=15.7
|
| 52 |
+
[GGML_PROF] GET_ROWS f32 <f32 [ 2048, 1, 1] 0.19 ms 0.01% calls=130 us/call=1.5
|
| 53 |
+
[GGML_PROF] MUL_MAT f32 <q8_0 [150144, 1, 1] 125.28 ms 7.46% calls=65 us/call=1927.3
|
| 54 |
+
|
| 55 |
+
build: de5122d87 (1)
|
benchmarks/profile-prefill.txt
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
| model | size | params | backend | threads | n_batch | n_ubatch | fa | lm | test | t/s |
|
| 2 |
+
| ------------------------------ | ---------: | ---------: | ---------- | ------: | ------: | -------: | --: | ---------: | --------------: | -------------------: |
|
| 3 |
+
| flint ?B Q4_K - Medium | 23.33 GiB | 39.79 B | CPU | 16 | 1024 | 1024 | 1 | mlock | pp2048 | 309.71 ± 0.00 |
|
| 4 |
+
|
| 5 |
+
[GGML_PROF] total_us=13581874
|
| 6 |
+
[GGML_PROF] GET_ROWS f32 <q8_0 [ 2048, 1024, 1] 5.90 ms 0.04% calls=4 us/call=1476.0
|
| 7 |
+
[GGML_PROF] RMS_NORM f32 <f32 [ 2048, 1024, 1] 125.01 ms 0.92% calls=388 us/call=322.2
|
| 8 |
+
[GGML_PROF] MUL_MAT f32 <q8_0 [ 4096, 1024, 1] 732.99 ms 5.40% calls=168 us/call=4363.0
|
| 9 |
+
[GGML_PROF] RMS_NORM f32 <f32 [ 128, 32,1024] 139.90 ms 1.03% calls=196 us/call=713.8
|
| 10 |
+
[GGML_PROF] MUL_MAT f32 <q8_0 [ 512, 1024, 1] 245.74 ms 1.81% calls=336 us/call=731.4
|
| 11 |
+
[GGML_PROF] RMS_NORM f32 <f32 [ 128, 4,1024] 50.24 ms 0.37% calls=196 us/call=256.3
|
| 12 |
+
[GGML_PROF] SET_ROWS f16 <f32 [ 512, 2048, 1] 19.08 ms 0.14% calls=112 us/call=170.4
|
| 13 |
+
[GGML_PROF] FLASH_ATTN_EXT f32 <f32 [ 128, 32,1024] 3199.22 ms 23.56% calls=196 us/call=16322.6
|
| 14 |
+
[GGML_PROF] MUL_MAT f32 <q8_0 [ 2048, 1024, 1] 948.76 ms 6.99% calls=308 us/call=3080.4
|
| 15 |
+
[GGML_PROF] ADD f32 <f32 [ 2048, 1024, 1] 88.97 ms 0.66% calls=1488 us/call=59.8
|
| 16 |
+
[GGML_PROF] MUL_MAT f32 <q8_0 [ 6144, 1024, 1] 138.57 ms 1.02% calls=16 us/call=8660.9
|
| 17 |
+
[GGML_PROF] GLU f32 <f32 [ 6144, 1024, 1] 12.83 ms 0.09% calls=8 us/call=1603.5
|
| 18 |
+
[GGML_PROF] ROPE f32 <f32 [ 128, 32,1024] 42.53 ms 0.31% calls=140 us/call=303.8
|
| 19 |
+
[GGML_PROF] ROPE f32 <f32 [ 128, 4,1024] 10.87 ms 0.08% calls=140 us/call=77.6
|
| 20 |
+
[GGML_PROF] SET_ROWS f16 <f32 [ 512, 1792, 1] 3.89 ms 0.03% calls=280 us/call=13.9
|
| 21 |
+
[GGML_PROF] MUL_MAT f32 <bf16 [ 256, 1024, 1] 197.14 ms 1.45% calls=184 us/call=1071.4
|
| 22 |
+
[GGML_PROF] UNARY f32 <f32 [ 256, 1024, 1] 11.94 ms 0.09% calls=184 us/call=64.9
|
| 23 |
+
[GGML_PROF] ARGSORT i32 <f32 [ 256, 1024, 1] 150.49 ms 1.11% calls=184 us/call=817.9
|
| 24 |
+
[GGML_PROF] GET_ROWS f32 <f32 [ 1, 6,1024] 2.21 ms 0.02% calls=184 us/call=12.0
|
| 25 |
+
[GGML_PROF] SUM_ROWS f32 <f32 [ 1, 1024, 1] 1.02 ms 0.01% calls=184 us/call=5.6
|
| 26 |
+
[GGML_PROF] CLAMP f32 <f32 [ 1, 1024, 1] 1.94 ms 0.01% calls=184 us/call=10.5
|
| 27 |
+
[GGML_PROF] DIV f32 <f32 [ 6, 1024, 1] 0.65 ms 0.00% calls=184 us/call=3.5
|
| 28 |
+
[GGML_PROF] MUL_MAT_ID f32 <iq3_s [ 512, 6,1024] 111.13 ms 0.82% calls=8 us/call=13891.1
|
| 29 |
+
[GGML_PROF] GLU f32 <f32 [ 512, 6,1024] 41.05 ms 0.30% calls=184 us/call=223.1
|
| 30 |
+
[GGML_PROF] UNARY f32 <f32 [ 512, 6,1024] 14.72 ms 0.11% calls=184 us/call=80.0
|
| 31 |
+
[GGML_PROF] POOL_1D f32 <f32 [ 1, 6,1024] 717.08 ms 5.28% calls=184 us/call=3897.2
|
| 32 |
+
[GGML_PROF] SCALE f32 <f32 [ 1, 6,1024] 6.38 ms 0.05% calls=552 us/call=11.6
|
| 33 |
+
[GGML_PROF] LOG f32 <f32 [ 1, 6,1024] 1.32 ms 0.01% calls=184 us/call=7.2
|
| 34 |
+
[GGML_PROF] UNARY f32 <f32 [ 1, 6,1024] 1.79 ms 0.01% calls=368 us/call=4.9
|
| 35 |
+
[GGML_PROF] CLAMP f32 <f32 [ 1, 6,1024] 8.17 ms 0.06% calls=184 us/call=44.4
|
| 36 |
+
[GGML_PROF] DIV f32 <f32 [ 512, 6,1024] 48.76 ms 0.36% calls=184 us/call=265.0
|
| 37 |
+
[GGML_PROF] MUL_MAT_ID f32 <q5_K [ 2048, 6,1024] 1450.95 ms 10.68% calls=116 us/call=12508.2
|
| 38 |
+
[GGML_PROF] MUL f32 <f32 [ 2048, 6,1024] 388.11 ms 2.86% calls=368 us/call=1054.7
|
| 39 |
+
[GGML_PROF] MUL_MAT f32 <q8_0 [ 1024, 1024, 1] 292.28 ms 2.15% calls=264 us/call=1107.1
|
| 40 |
+
[GGML_PROF] GLU f32 <f32 [ 1024, 1024, 1] 9.64 ms 0.07% calls=184 us/call=52.4
|
| 41 |
+
[GGML_PROF] MUL_MAT_ID f32 <q5_K [ 512, 6,1024] 1415.40 ms 10.42% calls=144 us/call=9829.2
|
| 42 |
+
[GGML_PROF] MUL_MAT_ID f32 <q8_0 [ 2048, 6,1024] 105.06 ms 0.77% calls=4 us/call=26264.0
|
| 43 |
+
[GGML_PROF] MUL_MAT_ID f32 <q6_K [ 2048, 6,1024] 62.41 ms 0.46% calls=4 us/call=15601.8
|
| 44 |
+
[GGML_PROF] MUL_MAT f32 <q5_K [ 4096, 1024, 1] 140.26 ms 1.03% calls=28 us/call=5009.4
|
| 45 |
+
[GGML_PROF] MUL_MAT f32 <q5_K [ 512, 1024, 1] 48.46 ms 0.36% calls=56 us/call=865.3
|
| 46 |
+
[GGML_PROF] MUL_MAT f32 <q5_K [ 2048, 1024, 1] 215.82 ms 1.59% calls=76 us/call=2839.8
|
| 47 |
+
[GGML_PROF] MUL_MAT_ID f32 <iq4_xs [ 512, 6,1024] 1376.81 ms 10.14% calls=192 us/call=7170.9
|
| 48 |
+
[GGML_PROF] MUL_MAT_ID f32 <iq4_xs [ 2048, 6,1024] 631.64 ms 4.65% calls=60 us/call=10527.4
|
| 49 |
+
[GGML_PROF] MUL_MAT_ID f32 <q4_K [ 512, 6,1024] 194.15 ms 1.43% calls=24 us/call=8089.7
|
| 50 |
+
[GGML_PROF] MUL_MAT f32 <q5_K [ 1024, 1024, 1] 146.41 ms 1.08% calls=96 us/call=1525.1
|
| 51 |
+
[GGML_PROF] MUL_MAT f32 <iq4_xs [ 1024, 1024, 1] 10.24 ms 0.08% calls=8 us/call=1280.6
|
| 52 |
+
[GGML_PROF] MUL_MAT f32 <iq4_xs [ 2048, 1024, 1] 4.50 ms 0.03% calls=4 us/call=1126.0
|
| 53 |
+
[GGML_PROF] GET_ROWS f32 <f32 [ 2048, 1, 1] 0.02 ms 0.00% calls=8 us/call=2.1
|
| 54 |
+
[GGML_PROF] ADD f32 <f32 [ 2048, 1, 1] 0.05 ms 0.00% calls=32 us/call=1.5
|
| 55 |
+
[GGML_PROF] RMS_NORM f32 <f32 [ 2048, 1, 1] 0.04 ms 0.00% calls=8 us/call=4.5
|
| 56 |
+
[GGML_PROF] MUL_MAT f32 <bf16 [ 256, 1, 1] 0.07 ms 0.00% calls=4 us/call=16.8
|
| 57 |
+
[GGML_PROF] UNARY f32 <f32 [ 256, 1, 1] 0.01 ms 0.00% calls=4 us/call=2.5
|
| 58 |
+
[GGML_PROF] ARGSORT i32 <f32 [ 256, 1, 1] 0.06 ms 0.00% calls=4 us/call=13.8
|
| 59 |
+
[GGML_PROF] GET_ROWS f32 <f32 [ 1, 6, 1] 0.01 ms 0.00% calls=4 us/call=1.2
|
| 60 |
+
[GGML_PROF] SUM_ROWS f32 <f32 [ 1, 1, 1] 0.01 ms 0.00% calls=4 us/call=1.5
|
| 61 |
+
[GGML_PROF] CLAMP f32 <f32 [ 1, 1, 1] 0.00 ms 0.00% calls=4 us/call=1.0
|
| 62 |
+
[GGML_PROF] DIV f32 <f32 [ 6, 1, 1] 0.00 ms 0.00% calls=4 us/call=1.0
|
| 63 |
+
[GGML_PROF] MUL_MAT_ID f32 <iq4_xs [ 512, 6, 1] 0.25 ms 0.00% calls=8 us/call=30.9
|
| 64 |
+
[GGML_PROF] GLU f32 <f32 [ 512, 6, 1] 0.01 ms 0.00% calls=4 us/call=2.2
|
| 65 |
+
[GGML_PROF] UNARY f32 <f32 [ 512, 6, 1] 0.01 ms 0.00% calls=4 us/call=1.5
|
| 66 |
+
[GGML_PROF] POOL_1D f32 <f32 [ 1, 6, 1] 0.02 ms 0.00% calls=4 us/call=5.8
|
| 67 |
+
[GGML_PROF] SCALE f32 <f32 [ 1, 6, 1] 0.01 ms 0.00% calls=12 us/call=1.1
|
| 68 |
+
[GGML_PROF] LOG f32 <f32 [ 1, 6, 1] 0.01 ms 0.00% calls=4 us/call=1.8
|
| 69 |
+
[GGML_PROF] UNARY f32 <f32 [ 1, 6, 1] 0.01 ms 0.00% calls=8 us/call=1.4
|
| 70 |
+
[GGML_PROF] CLAMP f32 <f32 [ 1, 6, 1] 0.00 ms 0.00% calls=4 us/call=1.0
|
| 71 |
+
[GGML_PROF] DIV f32 <f32 [ 512, 6, 1] 0.01 ms 0.00% calls=4 us/call=1.2
|
| 72 |
+
[GGML_PROF] MUL_MAT_ID f32 <iq4_xs [ 2048, 6, 1] 0.14 ms 0.00% calls=4 us/call=35.0
|
| 73 |
+
[GGML_PROF] MUL f32 <f32 [ 2048, 6, 1] 0.03 ms 0.00% calls=8 us/call=3.5
|
| 74 |
+
[GGML_PROF] MUL_MAT f32 <q8_0 [ 1024, 1, 1] 0.15 ms 0.00% calls=8 us/call=18.6
|
| 75 |
+
[GGML_PROF] GLU f32 <f32 [ 1024, 1, 1] 0.01 ms 0.00% calls=4 us/call=2.0
|
| 76 |
+
[GGML_PROF] MUL_MAT f32 <q8_0 [ 2048, 1, 1] 0.07 ms 0.00% calls=4 us/call=17.5
|
| 77 |
+
[GGML_PROF] MUL_MAT f32 <q8_0 [150144, 1, 1] 8.43 ms 0.06% calls=4 us/call=2106.2
|
| 78 |
+
|
| 79 |
+
build: de5122d87 (1)
|
benchmarks/summary.md
CHANGED
|
@@ -1,14 +1,42 @@
|
|
| 1 |
-
# flint CPU optimization
|
| 2 |
|
| 3 |
-
|
| 4 |
-
|
| 5 |
|
| 6 |
-
|
|
| 7 |
|---|---|---|---|
|
| 8 |
-
|
|
| 9 |
-
|
|
| 10 |
-
|
|
| 11 |
-
| tg128 (pp2048 run) | 32.9 | 37.3 | 1.13x |
|
| 12 |
|
| 13 |
-
|
| 14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# flint-UD-Q4_K_XL CPU optimization (Xeon Platinum 8559C, 16 threads)
|
| 2 |
|
| 3 |
+
`llama-bench -t 16 -fa on -lm mlock -b 1024 -ub 1024`, 3 interleaved rounds (stock / Qwen3.6 patch / this patch per round), median t/s.
|
| 4 |
+
Raw: `ab-interleaved-flint.csv`.
|
| 5 |
|
| 6 |
+
| variant | pp256 | pp2048 | tg128 |
|
| 7 |
|---|---|---|---|
|
| 8 |
+
| stock llama.cpp (de5122d) | 231.0 | 274.2 | 38.2 |
|
| 9 |
+
| Qwen3.6 CPU-OPT patch, unchanged | 264.4 | 307.8 | 42.1 |
|
| 10 |
+
| **this patch** | **295.8** | **306.7** | **42.8** |
|
|
|
|
| 11 |
|
| 12 |
+
Versus stock: pp256 1.28x, pp2048 1.12x, tg128 1.12x. Versus the Qwen patch alone, only pp256 (+12%) is clearly better;
|
| 13 |
+
decode (+2%) and pp2048 are within noise. Most of the gain comes from the Qwen3.6 patch's kernels also applying to flint.
|
| 14 |
+
|
| 15 |
+
## What is new (flint-specific)
|
| 16 |
+
flint-UD-Q4_K_XL is Q5_K 11.6 GiB + IQ4_XS 9.0 GiB + Q8_0 2.0 GiB (+ small Q4_K/Q6_K/IQ3_S).
|
| 17 |
+
1. IQ4_XS x Q8_K `vec_dot`: AVX512-VNNI (the x86 path had only AVX2). Unsigned LUT (+128) with `vpdpbusd`, bias removed
|
| 18 |
+
through `bsums`, L2 prefetch (`GGML_IQ4XS_PF`, default 40). Decode MUL_MAT_ID iq4_xs reaches ~97 GB/s.
|
| 19 |
+
2. Q5_K x Q8_K `vec_dot`: 5th bit merged with `vptestmb` + masked add instead of shift/and/or.
|
| 20 |
+
Bit-identical results to the previous VNNI version (KLD unchanged on Qwen3.6 as well).
|
| 21 |
+
Other contents are the Qwen3.6 patch (Q4_K/Q5_K/Q6_K VNNI, AMX tweaks, tiled MoE group 32). Its Gated-DeltaNet changes
|
| 22 |
+
do not apply to flint.
|
| 23 |
+
|
| 24 |
+
## Accuracy (wikitext-2 test, 32 x 512, vs stock logits)
|
| 25 |
+
| | KLD | same top-1 | PPL |
|
| 26 |
+
|---|---|---|---|
|
| 27 |
+
| stock vs stock (-t 16 vs -t 8) | 0.0000 | 100 % | 18.363 |
|
| 28 |
+
| Qwen3.6 patch unchanged | 0.0664 +- 0.0049 | 92.2 % | - |
|
| 29 |
+
| this patch | 0.0666 +- 0.0049 | ~92 % | **18.277** +- 0.787 |
|
| 30 |
+
|
| 31 |
+
PPL is not worse than stock (18.363 +- 0.795), but KLD is far larger than on Qwen3.6 (0.003-0.006), so this patch is
|
| 32 |
+
**not** numerically close to stock on flint. Bisect (`kld-bisect.log`, KLD when one VNNI kernel is disabled):
|
| 33 |
+
Q4_K 0.0670, Q5_K 0.0524, Q6_K 0.0685, IQ4_XS 0.0664; removing all of `quants.c` gives 0.0162.
|
| 34 |
+
So the Q4_K/Q5_K/Q6_K VNNI kernels carry most of the deviation and the new IQ4_XS kernel only ~0.0002.
|
| 35 |
+
I did not find a defect in them (official `test-quantize-fns` dot-product errors equal stock); my unverified guess is that
|
| 36 |
+
flint's 256-expert top-6 routing amplifies tiny numeric differences. The earlier flint_cpu_opt README reported KLD 0.2058.
|
| 37 |
+
|
| 38 |
+
## Profile (decode, 64 tokens)
|
| 39 |
+
MUL_MAT q8_0 41 % (attention, shared expert, lm_head; close to bandwidth bound), MUL_MAT_ID q5_K 22 %,
|
| 40 |
+
MUL_MAT q5_K 8 %, MUL_MAT_ID iq4_xs 8 %. Prefill: FLASH_ATTN_EXT 24 %, MUL_MAT_ID q5_K 21 %, q8_0 17 %, iq4_xs 15 %.
|
| 41 |
+
Prefetch distance, thread count and `--poll` sweeps showed no gain beyond noise.
|
| 42 |
+
Not done: flash-attention kernel work, Q8_0 decode kernel.
|
build.sh
CHANGED
|
@@ -1,4 +1,9 @@
|
|
| 1 |
-
#!/
|
|
|
|
| 2 |
set -e
|
|
|
|
|
|
|
|
|
|
| 3 |
cmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_NATIVE=ON -DGGML_CUDA=OFF -DLLAMA_CURL=OFF
|
| 4 |
-
cmake --build build -j$(nproc) --target llama-
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
# Build llama.cpp at patches/BASE_COMMIT with the flint CPU patch (Xeon with AVX512-VNNI + AMX).
|
| 3 |
set -e
|
| 4 |
+
git clone https://github.com/ggml-org/llama.cpp && cd llama.cpp
|
| 5 |
+
git fetch --depth 1 origin $(cat ../patches/BASE_COMMIT) && git checkout $(cat ../patches/BASE_COMMIT)
|
| 6 |
+
git apply ../patches/flint-cpu-opt.patch
|
| 7 |
cmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_NATIVE=ON -DGGML_CUDA=OFF -DLLAMA_CURL=OFF
|
| 8 |
+
cmake --build build -j$(nproc) --target llama-cli llama-server llama-bench llama-perplexity
|
| 9 |
+
# run: taskset -c 0-15 build/bin/llama-cli -m flint-UD-Q4_K_XL.gguf -t 16 -fa on -lm mlock
|
machine.txt
CHANGED
|
@@ -1,6 +1,5 @@
|
|
| 1 |
-
|
| 2 |
-
Threads
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
AMX buffer: 1716 MiB (Q8_0 2D tensors); CPU_REPACK: 864 MiB (Q4_K 8x8)
|
|
|
|
| 1 |
+
Model name: Intel(R) Xeon(R) Platinum 8559C
|
| 2 |
+
Threads: 16 (taskset -c 0-15, cgroup cpu.max 1600000/100000)
|
| 3 |
+
Build: GCC 14.2.0, cmake 3.31.6, -DGGML_NATIVE=ON (AVX512, VNNI, AMX-INT8)
|
| 4 |
+
llama.cpp base commit: de5122d87
|
| 5 |
+
Host was shared; single runs vary by roughly +-8%.
|
|
|
patches/BASE_COMMIT
CHANGED
|
@@ -1 +1 @@
|
|
| 1 |
-
|
|
|
|
| 1 |
+
de5122d879d00d2895c36be7e0cee94105aeeabd
|
patches/flint-cpu-opt.patch
CHANGED
|
@@ -1,3 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
diff --git a/ggml/src/ggml-cpu/amx/amx.cpp b/ggml/src/ggml-cpu/amx/amx.cpp
|
| 2 |
index e90c2797f..e8b61a2eb 100644
|
| 3 |
--- a/ggml/src/ggml-cpu/amx/amx.cpp
|
|
@@ -142,7 +172,7 @@ index 9f3a744b5..d23e4d971 100644
|
|
| 142 |
|
| 143 |
parallel_for_ggml(params, n_batch * NB, [&](int begin, int end) {
|
| 144 |
diff --git a/ggml/src/ggml-cpu/arch/x86/quants.c b/ggml/src/ggml-cpu/arch/x86/quants.c
|
| 145 |
-
index 21cd6312a..
|
| 146 |
--- a/ggml/src/ggml-cpu/arch/x86/quants.c
|
| 147 |
+++ b/ggml/src/ggml-cpu/arch/x86/quants.c
|
| 148 |
@@ -2118,7 +2118,89 @@ void ggml_vec_dot_q4_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const voi
|
|
@@ -236,7 +266,7 @@ index 21cd6312a..0e8aafa76 100644
|
|
| 236 |
|
| 237 |
const __m256i m4 = _mm256_set1_epi8(0xF);
|
| 238 |
|
| 239 |
-
@@ -2296,7 +2378,
|
| 240 |
|
| 241 |
uint32_t utmp[4];
|
| 242 |
|
|
@@ -260,6 +290,13 @@ index 21cd6312a..0e8aafa76 100644
|
|
| 260 |
+ const __m512i cr2 = K5_CNT(0, 2); // sub-blocks 4,6 : right shift s-4
|
| 261 |
+ const __m512i cr3 = K5_CNT(1, 3); // sub-blocks 5,7
|
| 262 |
+ #undef K5_CNT
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 263 |
+
|
| 264 |
+ static int k5pf = -1;
|
| 265 |
+ if (k5pf < 0) { const char * e = getenv("GGML_K5_PF"); k5pf = e ? atoi(e) : 48; }
|
|
@@ -307,10 +344,16 @@ index 21cd6312a..0e8aafa76 100644
|
|
| 307 |
+ const __m512i Q2 = _mm512_loadu_si512((const void *)(q8 + 128));
|
| 308 |
+ const __m512i Q3 = _mm512_loadu_si512((const void *)(q8 + 192));
|
| 309 |
+
|
| 310 |
-
+
|
| 311 |
-
+
|
| 312 |
-
+ const __m512i
|
| 313 |
-
+ const __m512i
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 314 |
+
|
| 315 |
+ const __m512i b0 = _mm512_shuffle_i64x2(Q0, Q1, 0x44);
|
| 316 |
+ const __m512i b1 = _mm512_shuffle_i64x2(Q0, Q1, 0xEE);
|
|
@@ -335,7 +378,7 @@ index 21cd6312a..0e8aafa76 100644
|
|
| 335 |
|
| 336 |
const __m256i m4 = _mm256_set1_epi8(0xF);
|
| 337 |
const __m128i mzero = _mm_setzero_si128();
|
| 338 |
-
@@ -2500,7 +
|
| 339 |
|
| 340 |
const int nb = n / QK_K;
|
| 341 |
|
|
@@ -418,84 +461,249 @@ index 21cd6312a..0e8aafa76 100644
|
|
| 418 |
|
| 419 |
const __m256i m3 = _mm256_set1_epi8(3);
|
| 420 |
const __m256i m15 = _mm256_set1_epi8(15);
|
| 421 |
-
|
| 422 |
-
|
| 423 |
-
|
| 424 |
-
|
| 425 |
-
|
| 426 |
-
|
| 427 |
-
|
| 428 |
-
|
| 429 |
-
+
|
| 430 |
-
+
|
| 431 |
-
+
|
| 432 |
-
+
|
| 433 |
-
+
|
| 434 |
-
+
|
| 435 |
-
+static int64_t g_prof_total = 0;
|
| 436 |
-
+
|
| 437 |
-
+static void ggml_prof_dump(void) {
|
| 438 |
-
+ if (g_prof_n == 0) return;
|
| 439 |
-
+ fprintf(stderr, "\n[GGML_PROF] total_us=%" PRId64 "\n", g_prof_total);
|
| 440 |
-
+ for (int i = 0; i < g_prof_n; ++i) {
|
| 441 |
-
+ fprintf(stderr, "[GGML_PROF] %-20s %-6s<%-6s [%6" PRId64 ",%5" PRId64 ",%4" PRId64 "] %9.2f ms %6.2f%% calls=%" PRId64 " us/call=%.1f\n",
|
| 442 |
-
+ g_prof_tab[i].op, g_prof_tab[i].type, g_prof_tab[i].ty0, g_prof_tab[i].ne0, g_prof_tab[i].ne1, g_prof_tab[i].ne2,
|
| 443 |
-
+ g_prof_tab[i].us/1000.0,
|
| 444 |
-
+ 100.0*g_prof_tab[i].us/(g_prof_total?g_prof_total:1),
|
| 445 |
-
+ g_prof_tab[i].calls,
|
| 446 |
-
+ (double)g_prof_tab[i].us/(g_prof_tab[i].calls?g_prof_tab[i].calls:1));
|
| 447 |
-
+ }
|
| 448 |
-
+ fflush(stderr);
|
| 449 |
-
+}
|
| 450 |
+
|
| 451 |
-
+static
|
| 452 |
-
+
|
| 453 |
-
+
|
| 454 |
-
+
|
| 455 |
-
+
|
| 456 |
-
+
|
| 457 |
-
+
|
| 458 |
-
+
|
| 459 |
-
+
|
| 460 |
-
+
|
| 461 |
-
+
|
| 462 |
+ }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 463 |
+ }
|
| 464 |
-
+
|
| 465 |
-
+
|
| 466 |
-
+
|
| 467 |
-
+
|
| 468 |
-
|
| 469 |
-
|
| 470 |
-
|
| 471 |
-
|
| 472 |
-
|
| 473 |
-
|
| 474 |
-
|
| 475 |
-
@@ -
|
| 476 |
-
|
| 477 |
-
|
| 478 |
|
| 479 |
-
+
|
| 480 |
-
+
|
| 481 |
-
+
|
| 482 |
-
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 483 |
+ }
|
| 484 |
-
+
|
| 485 |
-
+
|
| 486 |
-
|
| 487 |
-
|
| 488 |
-
|
| 489 |
-
|
| 490 |
-
|
| 491 |
-
|
| 492 |
-
|
| 493 |
-
|
| 494 |
-
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 495 |
+ }
|
| 496 |
-
|
|
|
|
| 497 |
|
| 498 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 499 |
diff --git a/ggml/src/ggml-cpu/tiled/tiled.cpp b/ggml/src/ggml-cpu/tiled/tiled.cpp
|
| 500 |
index 77e1a9945..06fd9a2d5 100644
|
| 501 |
--- a/ggml/src/ggml-cpu/tiled/tiled.cpp
|
|
@@ -511,3 +719,208 @@ index 77e1a9945..06fd9a2d5 100644
|
|
| 511 |
|
| 512 |
// like tiled_store_window, but the dst columns are not contiguous: col_ptrs[j] points at the
|
| 513 |
// start of dst column j, whose rows are contiguous (dim 0, nb0 == 4 bytes).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
diff --git a/ggml/include/ggml.h b/ggml/include/ggml.h
|
| 2 |
+
index d62a63104..0cc5ed9cb 100644
|
| 3 |
+
--- a/ggml/include/ggml.h
|
| 4 |
+
+++ b/ggml/include/ggml.h
|
| 5 |
+
@@ -2678,6 +2678,25 @@ extern "C" {
|
| 6 |
+
struct ggml_tensor * state,
|
| 7 |
+
int64_t K);
|
| 8 |
+
|
| 9 |
+
+ // Cache variant of ggml_gated_delta_net (single-snapshot, K == 1): instead of a gathered copy of the
|
| 10 |
+
+ // initial state, the state of sequence i is read straight from row ids[i] of the state cache, and the
|
| 11 |
+
+ // final state is written in place to row i of state_dst (a view of consecutive cache rows), so the caller
|
| 12 |
+
+ // needs no get_rows before and no cpy after the op.
|
| 13 |
+
+ // state_cache : [S_v*S_v*H_v, n_cells] f32, contiguous rows
|
| 14 |
+
+ // ids : [n_seqs] i32, source cell of every sequence
|
| 15 |
+
+ // state_dst : [S_v*S_v*H_v, n_seqs] f32 view into the cache (destination cells)
|
| 16 |
+
+ // The packed output keeps the layout of ggml_gated_delta_net; its snapshot part is left unwritten.
|
| 17 |
+
+ GGML_API struct ggml_tensor * ggml_gated_delta_net_cache(
|
| 18 |
+
+ struct ggml_context * ctx,
|
| 19 |
+
+ struct ggml_tensor * q,
|
| 20 |
+
+ struct ggml_tensor * k,
|
| 21 |
+
+ struct ggml_tensor * v,
|
| 22 |
+
+ struct ggml_tensor * g,
|
| 23 |
+
+ struct ggml_tensor * beta,
|
| 24 |
+
+ struct ggml_tensor * state_cache,
|
| 25 |
+
+ struct ggml_tensor * ids,
|
| 26 |
+
+ struct ggml_tensor * state_dst);
|
| 27 |
+
+
|
| 28 |
+
// DSA lightning indexer
|
| 29 |
+
//
|
| 30 |
+
// q: [n_embd_idx, n_head_idx, n_batch, ne3 ]
|
| 31 |
diff --git a/ggml/src/ggml-cpu/amx/amx.cpp b/ggml/src/ggml-cpu/amx/amx.cpp
|
| 32 |
index e90c2797f..e8b61a2eb 100644
|
| 33 |
--- a/ggml/src/ggml-cpu/amx/amx.cpp
|
|
|
|
| 172 |
|
| 173 |
parallel_for_ggml(params, n_batch * NB, [&](int begin, int end) {
|
| 174 |
diff --git a/ggml/src/ggml-cpu/arch/x86/quants.c b/ggml/src/ggml-cpu/arch/x86/quants.c
|
| 175 |
+
index 21cd6312a..9b65eebb2 100644
|
| 176 |
--- a/ggml/src/ggml-cpu/arch/x86/quants.c
|
| 177 |
+++ b/ggml/src/ggml-cpu/arch/x86/quants.c
|
| 178 |
@@ -2118,7 +2118,89 @@ void ggml_vec_dot_q4_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const voi
|
|
|
|
| 266 |
|
| 267 |
const __m256i m4 = _mm256_set1_epi8(0xF);
|
| 268 |
|
| 269 |
+
@@ -2296,7 +2378,110 @@ void ggml_vec_dot_q5_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const voi
|
| 270 |
|
| 271 |
uint32_t utmp[4];
|
| 272 |
|
|
|
|
| 290 |
+ const __m512i cr2 = K5_CNT(0, 2); // sub-blocks 4,6 : right shift s-4
|
| 291 |
+ const __m512i cr3 = K5_CNT(1, 3); // sub-blocks 5,7
|
| 292 |
+ #undef K5_CNT
|
| 293 |
+
+ // per-vector bit selectors: low 32 bytes test bit s, high 32 bytes test bit s+2 (sub-block pairs (0,2),(1,3),(4,6),(5,7))
|
| 294 |
+
+ #define K5_BM(a, b) _mm512_inserti64x4(_mm512_castsi256_si512(_mm256_set1_epi8((char)(1 << (a)))), _mm256_set1_epi8((char)(1 << (b))), 1)
|
| 295 |
+
+ const __m512i bm0 = K5_BM(0, 2);
|
| 296 |
+
+ const __m512i bm1 = K5_BM(1, 3);
|
| 297 |
+
+ const __m512i bm2 = K5_BM(4, 6);
|
| 298 |
+
+ const __m512i bm3 = K5_BM(5, 7);
|
| 299 |
+
+ #undef K5_BM
|
| 300 |
+
|
| 301 |
+ static int k5pf = -1;
|
| 302 |
+ if (k5pf < 0) { const char * e = getenv("GGML_K5_PF"); k5pf = e ? atoi(e) : 48; }
|
|
|
|
| 344 |
+ const __m512i Q2 = _mm512_loadu_si512((const void *)(q8 + 128));
|
| 345 |
+ const __m512i Q3 = _mm512_loadu_si512((const void *)(q8 + 192));
|
| 346 |
+
|
| 347 |
+
+ // a_k = nibble + 16 * bit(qh[l], sub-block). qhv holds qh (32 B) duplicated in both 256-bit halves;
|
| 348 |
+
+ // lanes 0-31 of a vector are sub-block s (low half) and 32-63 are sub-block s+2 (high half) -> per-half bit masks.
|
| 349 |
+
+ const __m512i n0 = _mm512_and_si512(v0, m4);
|
| 350 |
+
+ const __m512i a0 = _mm512_mask_add_epi8(n0, _mm512_test_epi8_mask(qhv, bm0), n0, m10);
|
| 351 |
+
+ const __m512i n1 = _mm512_and_si512(_mm512_srli_epi16(v0, 4), m4);
|
| 352 |
+
+ const __m512i a1 = _mm512_mask_add_epi8(n1, _mm512_test_epi8_mask(qhv, bm1), n1, m10);
|
| 353 |
+
+ const __m512i n2 = _mm512_and_si512(v1, m4);
|
| 354 |
+
+ const __m512i a2 = _mm512_mask_add_epi8(n2, _mm512_test_epi8_mask(qhv, bm2), n2, m10);
|
| 355 |
+
+ const __m512i n3 = _mm512_and_si512(_mm512_srli_epi16(v1, 4), m4);
|
| 356 |
+
+ const __m512i a3 = _mm512_mask_add_epi8(n3, _mm512_test_epi8_mask(qhv, bm3), n3, m10);
|
| 357 |
+
|
| 358 |
+ const __m512i b0 = _mm512_shuffle_i64x2(Q0, Q1, 0x44);
|
| 359 |
+ const __m512i b1 = _mm512_shuffle_i64x2(Q0, Q1, 0xEE);
|
|
|
|
| 378 |
|
| 379 |
const __m256i m4 = _mm256_set1_epi8(0xF);
|
| 380 |
const __m128i mzero = _mm_setzero_si128();
|
| 381 |
+
@@ -2500,7 +2685,81 @@ void ggml_vec_dot_q6_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const voi
|
| 382 |
|
| 383 |
const int nb = n / QK_K;
|
| 384 |
|
|
|
|
| 461 |
|
| 462 |
const __m256i m3 = _mm256_set1_epi8(3);
|
| 463 |
const __m256i m15 = _mm256_set1_epi8(15);
|
| 464 |
+
@@ -4078,7 +4337,75 @@ void ggml_vec_dot_iq4_xs_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const v
|
| 465 |
+
|
| 466 |
+
const int nb = n / QK_K;
|
| 467 |
+
|
| 468 |
+
-#if defined __AVX2__
|
| 469 |
+
+#if defined(__AVX512F__) && defined(__AVX512BW__) && defined(__AVX512VL__) && defined(__AVX512VNNI__)
|
| 470 |
+
+ // AVX512-VNNI path (IQ4_XS x Q8_K). 64 qs bytes = 4 sub-blocks (16 B each, low nibble -> values 0..15, high
|
| 471 |
+
+ // nibble -> values 16..31 of the same sub-block). The kvalues LUT is stored as unsigned (v + 128) so that
|
| 472 |
+
+ // vpdpbusd can be used with 32-bit accumulation; the +128 bias is removed once per super-block through bsums.
|
| 473 |
+
+ const __m512i lut = _mm512_broadcast_i32x4(_mm_xor_si128(_mm_loadu_si128((const __m128i *)kvalues_iq4nl), _mm_set1_epi8((char)0x80)));
|
| 474 |
+
+ const __m512i m4 = _mm512_set1_epi8(0xF);
|
| 475 |
+
+ const __m512i idxA = _mm512_setr_epi32(0,0,0,0, 1,1,1,1, 2,2,2,2, 3,3,3,3);
|
| 476 |
+
+ const __m512i idxB = _mm512_setr_epi32(4,4,4,4, 5,5,5,5, 6,6,6,6, 7,7,7,7);
|
| 477 |
+
+ const __m128i hsh = _mm_setr_epi16(0, 2, 4, 6, 8, 10, 12, 14);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 478 |
+
|
| 479 |
+
+ static int ipf = -1;
|
| 480 |
+
+ if (ipf < 0) { const char * e = getenv("GGML_IQ4XS_PF"); ipf = e ? atoi(e) : 40; }
|
| 481 |
+
+
|
| 482 |
+
+ __m512 acc = _mm512_setzero_ps();
|
| 483 |
+
+
|
| 484 |
+
+ for (int ibl = 0; ibl < nb; ++ibl) {
|
| 485 |
+
+ {
|
| 486 |
+
+ const char * pf = (const char *)(x + ibl + ipf);
|
| 487 |
+
+ _mm_prefetch(pf, _MM_HINT_T1);
|
| 488 |
+
+ _mm_prefetch(pf + 64, _MM_HINT_T1);
|
| 489 |
+
+ _mm_prefetch(pf + 128, _MM_HINT_T1);
|
| 490 |
+ }
|
| 491 |
+
+
|
| 492 |
+
+ // 6-bit sub-block scales (-32), 8 per super-block
|
| 493 |
+
+ uint32_t sl; memcpy(&sl, x[ibl].scales_l, 4);
|
| 494 |
+
+ const __m128i xl = _mm_cvtsi32_si128((int)sl);
|
| 495 |
+
+ const __m128i l8 = _mm_unpacklo_epi8(_mm_and_si128(xl, _mm_set1_epi8(0x0f)),
|
| 496 |
+
+ _mm_and_si128(_mm_srli_epi16(xl, 4), _mm_set1_epi8(0x0f)));
|
| 497 |
+
+ const __m128i h16 = _mm_slli_epi16(_mm_and_si128(_mm_srlv_epi16(_mm_set1_epi16((short)x[ibl].scales_h), hsh), _mm_set1_epi16(3)), 4);
|
| 498 |
+
+ const __m128i ls16 = _mm_sub_epi16(_mm_or_si128(_mm_cvtepu8_epi16(l8), h16), _mm_set1_epi16(32));
|
| 499 |
+
+ const __m512i ls512 = _mm512_castsi256_si512(_mm256_cvtepi16_epi32(ls16));
|
| 500 |
+
+ const __m512i sc0 = _mm512_permutexvar_epi32(idxA, ls512);
|
| 501 |
+
+ const __m512i sc1 = _mm512_permutexvar_epi32(idxB, ls512);
|
| 502 |
+
+
|
| 503 |
+
+ const uint8_t * qs = x[ibl].qs;
|
| 504 |
+
+ const int8_t * q8 = y[ibl].qs;
|
| 505 |
+
+
|
| 506 |
+
+ const __m512i q0 = _mm512_loadu_si512((const void *)(qs));
|
| 507 |
+
+ const __m512i q1 = _mm512_loadu_si512((const void *)(qs + 64));
|
| 508 |
+
+ const __m512i Y0 = _mm512_loadu_si512((const void *)(q8));
|
| 509 |
+
+ const __m512i Y1 = _mm512_loadu_si512((const void *)(q8 + 64));
|
| 510 |
+
+ const __m512i Y2 = _mm512_loadu_si512((const void *)(q8 + 128));
|
| 511 |
+
+ const __m512i Y3 = _mm512_loadu_si512((const void *)(q8 + 192));
|
| 512 |
+
+
|
| 513 |
+
+ const __m512i xl0 = _mm512_shuffle_epi8(lut, _mm512_and_si512(q0, m4));
|
| 514 |
+
+ const __m512i xh0 = _mm512_shuffle_epi8(lut, _mm512_and_si512(_mm512_srli_epi16(q0, 4), m4));
|
| 515 |
+
+ const __m512i xl1 = _mm512_shuffle_epi8(lut, _mm512_and_si512(q1, m4));
|
| 516 |
+
+ const __m512i xh1 = _mm512_shuffle_epi8(lut, _mm512_and_si512(_mm512_srli_epi16(q1, 4), m4));
|
| 517 |
+
+
|
| 518 |
+
+ __m512i p0 = _mm512_dpbusd_epi32(_mm512_setzero_si512(), xl0, _mm512_shuffle_i64x2(Y0, Y1, 0x88));
|
| 519 |
+
+ p0 = _mm512_dpbusd_epi32(p0, xh0, _mm512_shuffle_i64x2(Y0, Y1, 0xDD));
|
| 520 |
+
+ __m512i p1 = _mm512_dpbusd_epi32(_mm512_setzero_si512(), xl1, _mm512_shuffle_i64x2(Y2, Y3, 0x88));
|
| 521 |
+
+ p1 = _mm512_dpbusd_epi32(p1, xh1, _mm512_shuffle_i64x2(Y2, Y3, 0xDD));
|
| 522 |
+
+
|
| 523 |
+
+ __m512i sumi = _mm512_add_epi32(_mm512_mullo_epi32(p0, sc0), _mm512_mullo_epi32(p1, sc1));
|
| 524 |
+
+
|
| 525 |
+
+ // remove the +128 bias: 128 * sum_k ls_k * (bsums[2k] + bsums[2k+1])
|
| 526 |
+
+ const __m256i bs = _mm256_loadu_si256((const __m256i *)y[ibl].bsums);
|
| 527 |
+
+ const __m256i lsd = _mm256_set_m128i(_mm_unpackhi_epi16(ls16, ls16), _mm_unpacklo_epi16(ls16, ls16));
|
| 528 |
+
+ const __m512i corr = _mm512_slli_epi32(_mm512_zextsi256_si512(_mm256_madd_epi16(bs, lsd)), 7);
|
| 529 |
+
+ sumi = _mm512_sub_epi32(sumi, corr);
|
| 530 |
+
+
|
| 531 |
+
+ const float d = GGML_CPU_FP16_TO_FP32(x[ibl].d) * y[ibl].d;
|
| 532 |
+
+ acc = _mm512_fmadd_ps(_mm512_set1_ps(d), _mm512_cvtepi32_ps(sumi), acc);
|
| 533 |
+ }
|
| 534 |
+
+
|
| 535 |
+
+ *s = _mm512_reduce_add_ps(acc);
|
| 536 |
+
+
|
| 537 |
+
+#elif defined __AVX2__
|
| 538 |
+
|
| 539 |
+
const __m128i values128 = _mm_loadu_si128((const __m128i*)kvalues_iq4nl);
|
| 540 |
+
const __m128i m4b = _mm_set1_epi8(0x0f);
|
| 541 |
+
diff --git a/ggml/src/ggml-cpu/ops.cpp b/ggml/src/ggml-cpu/ops.cpp
|
| 542 |
+
index 85e17018c..119d3c997 100644
|
| 543 |
+
--- a/ggml/src/ggml-cpu/ops.cpp
|
| 544 |
+
+++ b/ggml/src/ggml-cpu/ops.cpp
|
| 545 |
+
@@ -5316,6 +5316,29 @@ static void ggml_compute_forward_get_rows_f32(
|
| 546 |
+
const int ith = params->ith;
|
| 547 |
+
const int nth = params->nth;
|
| 548 |
|
| 549 |
+
+ // few rows: parallelize across the row instead of across rows so that a single
|
| 550 |
+
+ // large gather (e.g. the recurrent state of a single sequence) uses all threads
|
| 551 |
+
+ if (nr < nth && nc >= 4096) {
|
| 552 |
+
+ const int64_t per = (nc + nth - 1)/nth;
|
| 553 |
+
+ const int64_t c0 = per*ith;
|
| 554 |
+
+ const int64_t c1 = MIN(c0 + per, nc);
|
| 555 |
+
+ if (c0 < c1) {
|
| 556 |
+
+ for (int64_t i = 0; i < nr; ++i) {
|
| 557 |
+
+ const int64_t i12 = i/(ne11*ne10);
|
| 558 |
+
+ const int64_t i11 = (i - i12*ne11*ne10)/ne10;
|
| 559 |
+
+ const int64_t i10 = (i - i12*ne11*ne10 - i11*ne10);
|
| 560 |
+
+ const int64_t i01 = *(int32_t *) ((char *) src1->data + i10*nb10 + i11*nb11 + i12*nb12);
|
| 561 |
+
+
|
| 562 |
+
+ GGML_ASSERT(i01 >= 0 && i01 < ne01);
|
| 563 |
+
+
|
| 564 |
+
+ memcpy((char *) dst->data + i10*nb1 + i11*nb2 + i12*nb3 + c0*sizeof(float),
|
| 565 |
+
+ (char *) src0->data + i01*nb01 + i11*nb02 + i12*nb03 + c0*sizeof(float),
|
| 566 |
+
+ (c1 - c0)*sizeof(float));
|
| 567 |
+
+ }
|
| 568 |
+ }
|
| 569 |
+
+ return;
|
| 570 |
+
+ }
|
| 571 |
+
+
|
| 572 |
+
// rows per thread
|
| 573 |
+
const int dr = (nr + nth - 1)/nth;
|
| 574 |
+
|
| 575 |
+
@@ -11108,6 +11131,9 @@ static void ggml_compute_forward_gated_delta_net_one_chunk(
|
| 576 |
+
ggml_tensor * src_g = dst->src[3];
|
| 577 |
+
ggml_tensor * src_beta = dst->src[4];
|
| 578 |
+
ggml_tensor * src_state = dst->src[5];
|
| 579 |
+
+ // cache mode (see ggml_gated_delta_net_cache): src[6] = source cell ids, src[7] = in-place destination view
|
| 580 |
+
+ const ggml_tensor * src_ids = dst->src[6];
|
| 581 |
+
+ const ggml_tensor * src_sdst = dst->src[7];
|
| 582 |
+
|
| 583 |
+
const int64_t S_v = src_v->ne[0];
|
| 584 |
+
const int64_t H = src_v->ne[1];
|
| 585 |
+
@@ -11119,7 +11145,7 @@ static void ggml_compute_forward_gated_delta_net_one_chunk(
|
| 586 |
+
GGML_ASSERT(ggml_is_contiguous_rows(src_v));
|
| 587 |
+
GGML_ASSERT(ggml_is_contiguous(src_g));
|
| 588 |
+
GGML_ASSERT(ggml_is_contiguous(src_beta));
|
| 589 |
+
- GGML_ASSERT(ggml_is_contiguous(src_state));
|
| 590 |
+
+ GGML_ASSERT(src_ids ? src_state->nb[1] == (size_t) (S_v * S_v * H) * sizeof(float) : ggml_is_contiguous(src_state));
|
| 591 |
+
|
| 592 |
+
GGML_ASSERT(src_g->ne[0] == 1 || src_g->ne[0] == S_v);
|
| 593 |
+
GGML_ASSERT(src_beta->ne[0] == 1);
|
| 594 |
+
@@ -11139,6 +11165,7 @@ static void ggml_compute_forward_gated_delta_net_one_chunk(
|
| 595 |
+
// K (snapshot slot count) is an op param; state holds s0 only [S_v, S_v, H, n_seqs].
|
| 596 |
+
const int64_t K = ggml_get_op_params_i32(dst, 0);
|
| 597 |
+
GGML_ASSERT(K >= 1);
|
| 598 |
+
+ GGML_ASSERT(!src_ids || K == 1);
|
| 599 |
+
// per-seq stride in floats (seq s starts at state + s * seq_stride)
|
| 600 |
+
const int64_t state_seq_stride = src_state->nb[3] / sizeof(float);
|
| 601 |
+
|
| 602 |
+
@@ -11182,13 +11209,18 @@ static void ggml_compute_forward_gated_delta_net_one_chunk(
|
| 603 |
+
// For K>1, work in scratch and copy out per-token when the slot is in range.
|
| 604 |
+
float * s_out = (K > 1)
|
| 605 |
+
? state_work
|
| 606 |
+
- : state_out_base + (iv3 * H + iv1) * S_v * S_v;
|
| 607 |
+
+ : (src_sdst
|
| 608 |
+
+ ? (float *) src_sdst->data + iv3 * (src_sdst->nb[1] / sizeof(float)) + iv1 * S_v * S_v
|
| 609 |
+
+ : state_out_base + (iv3 * H + iv1) * S_v * S_v);
|
| 610 |
+
|
| 611 |
+
// copy input state into the working buffer and operate in-place
|
| 612 |
+
// state layout [S_v, S_v, H, n_seqs]: seq iv3 starts at iv3 * state_seq_stride.
|
| 613 |
+
- const float * s_in = state_in_base + iv3 * state_seq_stride + iv1 * S_v * S_v;
|
| 614 |
+
- memcpy(s_out, s_in, S_v * S_v * sizeof(float));
|
| 615 |
+
-
|
| 616 |
+
+ const float * s_in = src_ids
|
| 617 |
+
+ ? state_in_base + (int64_t) ((const int32_t *) src_ids->data)[iv3] * (src_state->nb[1] / sizeof(float)) + iv1 * S_v * S_v
|
| 618 |
+
+ : state_in_base + iv3 * state_seq_stride + iv1 * S_v * S_v;
|
| 619 |
+
+ if (s_out != s_in) {
|
| 620 |
+
+ memcpy(s_out, s_in, S_v * S_v * sizeof(float));
|
| 621 |
+ }
|
| 622 |
+
// attn output pointer for first token of this (head, seq)
|
| 623 |
+
float * attn_data = attn_out_base + (iv3 * n_tokens * H + iv1) * S_v;
|
| 624 |
|
| 625 |
+
@@ -11203,6 +11235,56 @@ static void ggml_compute_forward_gated_delta_net_one_chunk(
|
| 626 |
+
// state is stored transposed: s_out[j*S_v + i] = S[i][j]
|
| 627 |
+
// so row j of s_out = column j of S (contiguous access)
|
| 628 |
+
|
| 629 |
+
+ bool gdn_done = false;
|
| 630 |
+
+#if defined(__AVX512F__)
|
| 631 |
+
+ if (!kda && S_v == 128) {
|
| 632 |
+
+ // Fused 2-pass update for the scalar-gate case (non-KDA), S_v == 128:
|
| 633 |
+
+ // delta[j] = (v[j] - g * dot(S_j, k)) * beta
|
| 634 |
+
+ // S_j <- g * S_j + delta[j] * k ; out[j] = dot(S_j, q) * scale
|
| 635 |
+
+ // Same element-wise fma as the reference path; only the dot rounding order differs.
|
| 636 |
+
+ const float g = expf(g_d[0]);
|
| 637 |
+
+ __m512 kv[8], qv[8];
|
| 638 |
+
+ for (int i = 0; i < 8; ++i) {
|
| 639 |
+
+ kv[i] = _mm512_loadu_ps(k_d + 16 * i);
|
| 640 |
+
+ qv[i] = _mm512_loadu_ps(q_d + 16 * i);
|
| 641 |
+
+ }
|
| 642 |
+
+ for (int64_t j = 0; j < 128; j += 4) {
|
| 643 |
+
+ float sums[4];
|
| 644 |
+
+ for (int r = 0; r < 4; ++r) {
|
| 645 |
+
+ const float * row = s_out + (j + r) * 128;
|
| 646 |
+
+ __m512 a0 = _mm512_mul_ps(_mm512_loadu_ps(row), kv[0]);
|
| 647 |
+
+ __m512 a1 = _mm512_mul_ps(_mm512_loadu_ps(row + 16), kv[1]);
|
| 648 |
+
+ a0 = _mm512_fmadd_ps(_mm512_loadu_ps(row + 32), kv[2], a0);
|
| 649 |
+
+ a1 = _mm512_fmadd_ps(_mm512_loadu_ps(row + 48), kv[3], a1);
|
| 650 |
+
+ a0 = _mm512_fmadd_ps(_mm512_loadu_ps(row + 64), kv[4], a0);
|
| 651 |
+
+ a1 = _mm512_fmadd_ps(_mm512_loadu_ps(row + 80), kv[5], a1);
|
| 652 |
+
+ a0 = _mm512_fmadd_ps(_mm512_loadu_ps(row + 96), kv[6], a0);
|
| 653 |
+
+ a1 = _mm512_fmadd_ps(_mm512_loadu_ps(row + 112), kv[7], a1);
|
| 654 |
+
+ sums[r] = _mm512_reduce_add_ps(_mm512_add_ps(a0, a1));
|
| 655 |
+
+ }
|
| 656 |
+
+ for (int r = 0; r < 4; ++r) {
|
| 657 |
+
+ delta[j + r] = (v_d[j + r] - g * sums[r]) * beta_val;
|
| 658 |
+
+ }
|
| 659 |
+
+ }
|
| 660 |
+
+ const __m512 gv = _mm512_set1_ps(g);
|
| 661 |
+
+ for (int64_t j = 0; j < 128; ++j) {
|
| 662 |
+
+ float * row = s_out + j * 128;
|
| 663 |
+
+ const __m512 dv = _mm512_set1_ps(delta[j]);
|
| 664 |
+
+ __m512 aq0 = _mm512_setzero_ps(), aq1 = _mm512_setzero_ps();
|
| 665 |
+
+ for (int i = 0; i < 8; i += 2) {
|
| 666 |
+
+ const __m512 s0 = _mm512_fmadd_ps(dv, kv[i], _mm512_mul_ps(gv, _mm512_loadu_ps(row + 16 * i)));
|
| 667 |
+
+ const __m512 s1 = _mm512_fmadd_ps(dv, kv[i + 1], _mm512_mul_ps(gv, _mm512_loadu_ps(row + 16 * (i + 1))));
|
| 668 |
+
+ _mm512_storeu_ps(row + 16 * i, s0);
|
| 669 |
+
+ _mm512_storeu_ps(row + 16 * (i + 1), s1);
|
| 670 |
+
+ aq0 = _mm512_fmadd_ps(s0, qv[i], aq0);
|
| 671 |
+
+ aq1 = _mm512_fmadd_ps(s1, qv[i + 1], aq1);
|
| 672 |
+
+ }
|
| 673 |
+
+ attn_data[j] = _mm512_reduce_add_ps(_mm512_add_ps(aq0, aq1)) * scale;
|
| 674 |
+
+ }
|
| 675 |
+
+ gdn_done = true;
|
| 676 |
+
+ }
|
| 677 |
+
+#endif
|
| 678 |
+
+ if (!gdn_done) {
|
| 679 |
+
if (kda) {
|
| 680 |
+
// precompute exp(g) into delta scratch (reused below)
|
| 681 |
+
for (int64_t i = 0; i < S_v; ++i) {
|
| 682 |
+
@@ -11235,6 +11317,8 @@ static void ggml_compute_forward_gated_delta_net_one_chunk(
|
| 683 |
+
attn_data[j] = sum * scale;
|
| 684 |
+
}
|
| 685 |
+
|
| 686 |
+
+ }
|
| 687 |
+
+
|
| 688 |
+
attn_data += S_v * H; // advance to next token
|
| 689 |
+
|
| 690 |
+
if (K > 1) {
|
| 691 |
+
diff --git a/ggml/src/ggml-cpu/repack.cpp b/ggml/src/ggml-cpu/repack.cpp
|
| 692 |
+
index 9282ca299..0431b7ada 100644
|
| 693 |
+
--- a/ggml/src/ggml-cpu/repack.cpp
|
| 694 |
+
+++ b/ggml/src/ggml-cpu/repack.cpp
|
| 695 |
+
@@ -5009,7 +5009,10 @@ static const ggml::cpu::tensor_traits * ggml_repack_get_optimal_repack_type(cons
|
| 696 |
+
#endif
|
| 697 |
+
}
|
| 698 |
+
} else if (cur->type == GGML_TYPE_Q4_K) {
|
| 699 |
+
- if (ggml_cpu_has_avx2()) {
|
| 700 |
+
+ const char * rp_q4k = getenv("GGML_REPACK_Q4K");
|
| 701 |
+
+ // Xeon 8559C: the AVX512-VNNI Q4_K vec_dot beats the AVX2 8x8 repack on decode+prefill; opt in with GGML_REPACK_Q4K=1
|
| 702 |
+
+ const bool q4k_repack = (rp_q4k && rp_q4k[0] == '1');
|
| 703 |
+
+ if (q4k_repack && ggml_cpu_has_avx2()) {
|
| 704 |
+
if (cur->ne[1] % 8 == 0) {
|
| 705 |
+
return &q4_K_8x8_q8_K;
|
| 706 |
+
}
|
| 707 |
diff --git a/ggml/src/ggml-cpu/tiled/tiled.cpp b/ggml/src/ggml-cpu/tiled/tiled.cpp
|
| 708 |
index 77e1a9945..06fd9a2d5 100644
|
| 709 |
--- a/ggml/src/ggml-cpu/tiled/tiled.cpp
|
|
|
|
| 719 |
|
| 720 |
// like tiled_store_window, but the dst columns are not contiguous: col_ptrs[j] points at the
|
| 721 |
// start of dst column j, whose rows are contiguous (dim 0, nb0 == 4 bytes).
|
| 722 |
+
diff --git a/ggml/src/ggml.c b/ggml/src/ggml.c
|
| 723 |
+
index 5d8449a88..203f15e43 100644
|
| 724 |
+
--- a/ggml/src/ggml.c
|
| 725 |
+
+++ b/ggml/src/ggml.c
|
| 726 |
+
@@ -6416,6 +6416,59 @@ struct ggml_tensor * ggml_solve_tri(
|
| 727 |
+
|
| 728 |
+
// ggml_gated_delta_net
|
| 729 |
+
|
| 730 |
+
+struct ggml_tensor * ggml_gated_delta_net_cache(
|
| 731 |
+
+ struct ggml_context * ctx,
|
| 732 |
+
+ struct ggml_tensor * q,
|
| 733 |
+
+ struct ggml_tensor * k,
|
| 734 |
+
+ struct ggml_tensor * v,
|
| 735 |
+
+ struct ggml_tensor * g,
|
| 736 |
+
+ struct ggml_tensor * beta,
|
| 737 |
+
+ struct ggml_tensor * state_cache,
|
| 738 |
+
+ struct ggml_tensor * ids,
|
| 739 |
+
+ struct ggml_tensor * state_dst) {
|
| 740 |
+
+ GGML_ASSERT(ggml_is_contiguous_rows(q));
|
| 741 |
+
+ GGML_ASSERT(ggml_is_contiguous_rows(k));
|
| 742 |
+
+ GGML_ASSERT(ggml_is_contiguous_rows(v));
|
| 743 |
+
+ GGML_ASSERT(ggml_is_contiguous(g));
|
| 744 |
+
+ GGML_ASSERT(ggml_is_contiguous(beta));
|
| 745 |
+
+ GGML_ASSERT(q->type == GGML_TYPE_F32 && k->type == GGML_TYPE_F32 && v->type == GGML_TYPE_F32);
|
| 746 |
+
+ GGML_ASSERT(g->type == GGML_TYPE_F32 && beta->type == GGML_TYPE_F32);
|
| 747 |
+
+
|
| 748 |
+
+ const int64_t S_v = v->ne[0];
|
| 749 |
+
+ const int64_t H = v->ne[1];
|
| 750 |
+
+ const int64_t n_tokens = v->ne[2];
|
| 751 |
+
+ const int64_t n_seqs = v->ne[3];
|
| 752 |
+
+
|
| 753 |
+
+ GGML_ASSERT(g->ne[0] == 1 || g->ne[0] == S_v);
|
| 754 |
+
+ GGML_ASSERT(beta->ne[0] == 1);
|
| 755 |
+
+
|
| 756 |
+
+ GGML_ASSERT(state_cache->type == GGML_TYPE_F32);
|
| 757 |
+
+ GGML_ASSERT(state_cache->ne[0] == S_v * S_v * H);
|
| 758 |
+
+ GGML_ASSERT(state_cache->nb[1] == (size_t) (S_v * S_v * H) * sizeof(float));
|
| 759 |
+
+ GGML_ASSERT(ids->type == GGML_TYPE_I32);
|
| 760 |
+
+ GGML_ASSERT(ids->ne[0] == n_seqs);
|
| 761 |
+
+ GGML_ASSERT(state_dst->type == GGML_TYPE_F32);
|
| 762 |
+
+ GGML_ASSERT(state_dst->ne[0] == S_v * S_v * H && state_dst->ne[1] == n_seqs);
|
| 763 |
+
+ GGML_ASSERT(state_dst->nb[1] == state_cache->nb[1]);
|
| 764 |
+
+
|
| 765 |
+
+ const int64_t ne[4] = { S_v * H, n_tokens * n_seqs + S_v * n_seqs, 1, 1 };
|
| 766 |
+
+ struct ggml_tensor * result = ggml_new_tensor(ctx, GGML_TYPE_F32, 4, ne);
|
| 767 |
+
+
|
| 768 |
+
+ ggml_set_op_params_i32(result, 0, 1); // K == 1
|
| 769 |
+
+
|
| 770 |
+
+ result->op = GGML_OP_GATED_DELTA_NET;
|
| 771 |
+
+ result->src[0] = q;
|
| 772 |
+
+ result->src[1] = k;
|
| 773 |
+
+ result->src[2] = v;
|
| 774 |
+
+ result->src[3] = g;
|
| 775 |
+
+ result->src[4] = beta;
|
| 776 |
+
+ result->src[5] = state_cache;
|
| 777 |
+
+ result->src[6] = ids;
|
| 778 |
+
+ result->src[7] = state_dst;
|
| 779 |
+
+
|
| 780 |
+
+ return result;
|
| 781 |
+
+}
|
| 782 |
+
+
|
| 783 |
+
struct ggml_tensor * ggml_gated_delta_net(
|
| 784 |
+
struct ggml_context * ctx,
|
| 785 |
+
struct ggml_tensor * q,
|
| 786 |
+
diff --git a/src/llama-graph.cpp b/src/llama-graph.cpp
|
| 787 |
+
index 7309705dc..de5403dbe 100644
|
| 788 |
+
--- a/src/llama-graph.cpp
|
| 789 |
+
+++ b/src/llama-graph.cpp
|
| 790 |
+
@@ -3915,6 +3915,13 @@ ggml_tensor * llm_graph_context::build_rs(
|
| 791 |
+
// {state_size, rs_size} -> {state_size, n_rs - i0}
|
| 792 |
+
const int64_t i0 = n_rs - state_copy->ne[0];
|
| 793 |
+
|
| 794 |
+
+ // custom getter + no extra states: nothing to gather or copy
|
| 795 |
+
+ if (get_state_rows && n_rs == (uint32_t) n_seqs) {
|
| 796 |
+
+ ggml_tensor * output_states = get_state_rows(ctx0, states, state_copy_main);
|
| 797 |
+
+ ggml_build_forward_expand(gf, output_states);
|
| 798 |
+
+ return output_states;
|
| 799 |
+
+ }
|
| 800 |
+
+
|
| 801 |
+
ggml_tensor * states_all = ggml_get_rows(ctx0, states, state_copy);
|
| 802 |
+
|
| 803 |
+
ggml_tensor * output_states = get_state_rows ?
|
| 804 |
+
diff --git a/src/models/delta-net-base.cpp b/src/models/delta-net-base.cpp
|
| 805 |
+
index 2e15777ee..efc8c0e8e 100644
|
| 806 |
+
--- a/src/models/delta-net-base.cpp
|
| 807 |
+
+++ b/src/models/delta-net-base.cpp
|
| 808 |
+
@@ -521,6 +521,46 @@ ggml_tensor * llm_build_delta_net_base::build_conv_state(
|
| 809 |
+
return conv_input;
|
| 810 |
+
}
|
| 811 |
+
|
| 812 |
+
+ggml_tensor * llm_build_delta_net_base::build_recurrent_attn_cache(
|
| 813 |
+
+ llm_graph_input_rs * inp,
|
| 814 |
+
+ ggml_tensor * ssm_states_all,
|
| 815 |
+
+ ggml_tensor * state_cache,
|
| 816 |
+
+ ggml_tensor * q,
|
| 817 |
+
+ ggml_tensor * k,
|
| 818 |
+
+ ggml_tensor * v,
|
| 819 |
+
+ ggml_tensor * g,
|
| 820 |
+
+ ggml_tensor * b,
|
| 821 |
+
+ int il) {
|
| 822 |
+
+ const auto * mctx_cur = inp->mctx;
|
| 823 |
+
+ const auto kv_head = mctx_cur->get_head();
|
| 824 |
+
+
|
| 825 |
+
+ const int64_t S_v = v->ne[0];
|
| 826 |
+
+ const int64_t H_v = v->ne[1];
|
| 827 |
+
+ const int64_t n_seq_tokens = q->ne[2];
|
| 828 |
+
+ const int64_t n_seqs = q->ne[3];
|
| 829 |
+
+
|
| 830 |
+
+ GGML_ASSERT(n_seqs == 1 && cparams.n_rs_seq == 0);
|
| 831 |
+
+
|
| 832 |
+
+ ggml_tensor * state_dst = ggml_view_2d(ctx0, ssm_states_all, hparams.n_embd_s(), n_seqs, ssm_states_all->nb[1],
|
| 833 |
+
+ kv_head * hparams.n_embd_s() * ggml_element_size(ssm_states_all));
|
| 834 |
+
+
|
| 835 |
+
+ ggml_tensor * result = ggml_gated_delta_net_cache(ctx0, q, k, v, g, b, state_cache, inp->s_copy_main, state_dst);
|
| 836 |
+
+ if (n_seq_tokens == 1) {
|
| 837 |
+
+ res->add_fused_node({LLM_FUSED_OP_GDN_AR, result, il});
|
| 838 |
+
+ } else {
|
| 839 |
+
+ res->add_fused_node({LLM_FUSED_OP_GDN_CH, result, il});
|
| 840 |
+
+ }
|
| 841 |
+
+
|
| 842 |
+
+ ggml_tensor * output = ggml_view_4d(ctx0, result,
|
| 843 |
+
+ S_v, H_v, n_seq_tokens, n_seqs,
|
| 844 |
+
+ ggml_row_size(result->type, S_v),
|
| 845 |
+
+ ggml_row_size(result->type, S_v * H_v),
|
| 846 |
+
+ ggml_row_size(result->type, S_v * H_v * n_seq_tokens), 0);
|
| 847 |
+
+ cb(output, "attn_output", il);
|
| 848 |
+
+
|
| 849 |
+
+ return output;
|
| 850 |
+
+}
|
| 851 |
+
+
|
| 852 |
+
ggml_tensor * llm_build_delta_net_base::build_recurrent_attn(
|
| 853 |
+
llm_graph_input_rs * inp,
|
| 854 |
+
ggml_tensor * ssm_states_all,
|
| 855 |
+
diff --git a/src/models/models.h b/src/models/models.h
|
| 856 |
+
index 5d9b6077a..d0ba683fc 100644
|
| 857 |
+
--- a/src/models/models.h
|
| 858 |
+
+++ b/src/models/models.h
|
| 859 |
+
@@ -88,6 +88,19 @@ struct llm_build_delta_net_base : public llm_graph_context {
|
| 860 |
+
|
| 861 |
+
// run delta-net attention and write the new recurrent state(s) back to ssm_states_all
|
| 862 |
+
// s: (head_v_dim, head_v_dim, num_v_heads, n_seqs); returns output: (head_v_dim, num_v_heads, n_seq_tokens, n_seqs)
|
| 863 |
+
+ // single-sequence fast path: reads the state straight from the cache and updates it in place
|
| 864 |
+
+ // (no get_rows before, no cpy after); only valid for n_rs_seq == 0, n_seqs == 1 and the fused GDN ops
|
| 865 |
+
+ ggml_tensor * build_recurrent_attn_cache(
|
| 866 |
+
+ llm_graph_input_rs * inp,
|
| 867 |
+
+ ggml_tensor * ssm_states_all,
|
| 868 |
+
+ ggml_tensor * state_cache,
|
| 869 |
+
+ ggml_tensor * q,
|
| 870 |
+
+ ggml_tensor * k,
|
| 871 |
+
+ ggml_tensor * v,
|
| 872 |
+
+ ggml_tensor * g,
|
| 873 |
+
+ ggml_tensor * b,
|
| 874 |
+
+ int il);
|
| 875 |
+
+
|
| 876 |
+
ggml_tensor * build_recurrent_attn(
|
| 877 |
+
llm_graph_input_rs * inp,
|
| 878 |
+
ggml_tensor * ssm_states_all,
|
| 879 |
+
diff --git a/src/models/qwen35moe.cpp b/src/models/qwen35moe.cpp
|
| 880 |
+
index 939f10f7f..ffb396c1c 100644
|
| 881 |
+
--- a/src/models/qwen35moe.cpp
|
| 882 |
+
+++ b/src/models/qwen35moe.cpp
|
| 883 |
+
@@ -1,3 +1,4 @@
|
| 884 |
+
+#include <cstdlib>
|
| 885 |
+
#include "models.h"
|
| 886 |
+
#include "llama-memory-recurrent.h"
|
| 887 |
+
|
| 888 |
+
@@ -406,9 +407,24 @@ ggml_tensor * llama_model_qwen35moe::graph::build_layer_attn_linear(
|
| 889 |
+
|
| 890 |
+
ggml_tensor * conv_input = build_conv_state(inp, conv_states_all, qkv_mixed, conv_kernel_size, conv_channels, il);
|
| 891 |
+
|
| 892 |
+
- ggml_tensor * state = build_rs(inp, ssm_states_all, hparams.n_embd_s(), n_seqs);
|
| 893 |
+
- state = ggml_reshape_4d(ctx0, state, head_v_dim, head_v_dim, num_v_heads, n_seqs);
|
| 894 |
+
- cb(state, "state_predelta", il);
|
| 895 |
+
+ // Single-sequence decode/prefill fast path (CPU GDN): read the recurrent state straight from the cache and
|
| 896 |
+
+ // update it in place, instead of get_rows + gdn + cpy. Disable with LLAMA_GDN_NO_INPLACE=1.
|
| 897 |
+
+ static const bool gdn_inplace_allowed = getenv("LLAMA_GDN_NO_INPLACE") == nullptr;
|
| 898 |
+
+ const bool gdn_inplace = gdn_inplace_allowed && n_seqs == 1 && cparams.n_rs_seq == 0 &&
|
| 899 |
+
+ (n_seq_tokens == 1 ? cparams.fused_gdn_ar : cparams.fused_gdn_ch) &&
|
| 900 |
+
+ mctx_cur->get_n_rs() == 1;
|
| 901 |
+
+
|
| 902 |
+
+ ggml_tensor * state = nullptr;
|
| 903 |
+
+ ggml_tensor * state_cache = nullptr;
|
| 904 |
+
+ if (gdn_inplace) {
|
| 905 |
+
+ // the custom getter hands back the cache itself; build_rs still orders the optional state clearing
|
| 906 |
+
+ state_cache = build_rs(inp, ssm_states_all, hparams.n_embd_s(), n_seqs,
|
| 907 |
+
+ [](ggml_context *, ggml_tensor * states, ggml_tensor *) { return states; });
|
| 908 |
+
+ } else {
|
| 909 |
+
+ state = build_rs(inp, ssm_states_all, hparams.n_embd_s(), n_seqs);
|
| 910 |
+
+ state = ggml_reshape_4d(ctx0, state, head_v_dim, head_v_dim, num_v_heads, n_seqs);
|
| 911 |
+
+ cb(state, "state_predelta", il);
|
| 912 |
+
+ }
|
| 913 |
+
|
| 914 |
+
ggml_tensor * conv_output_proper = ggml_ssm_conv(ctx0, conv_input, conv_kernel);
|
| 915 |
+
cb(conv_output_proper, "conv_output_raw", il);
|
| 916 |
+
@@ -467,7 +483,9 @@ ggml_tensor * llama_model_qwen35moe::graph::build_layer_attn_linear(
|
| 917 |
+
cb(k_conv, "k_conv_predelta", il);
|
| 918 |
+
cb(v_conv, "v_conv_predelta", il);
|
| 919 |
+
|
| 920 |
+
- ggml_tensor * output = build_recurrent_attn(inp, ssm_states_all, q_conv, k_conv, v_conv, gate, beta, state, il);
|
| 921 |
+
+ ggml_tensor * output = gdn_inplace
|
| 922 |
+
+ ? build_recurrent_attn_cache(inp, ssm_states_all, state_cache, q_conv, k_conv, v_conv, gate, beta, il)
|
| 923 |
+
+ : build_recurrent_attn(inp, ssm_states_all, q_conv, k_conv, v_conv, gate, beta, state, il);
|
| 924 |
+
|
| 925 |
+
// z: [head_dim, n_heads, n_tokens, n_seqs] -> [n_heads * n_tokens * n_seqs, head_dim]
|
| 926 |
+
ggml_tensor * z_2d = ggml_reshape_4d(ctx0, z, head_v_dim, num_v_heads, n_seq_tokens, n_seqs);
|
patches/optional-profiler.patch
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
diff --git a/ggml/src/ggml-cpu/ggml-cpu.c b/ggml/src/ggml-cpu/ggml-cpu.c
|
| 2 |
-
index
|
| 3 |
--- a/ggml/src/ggml-cpu/ggml-cpu.c
|
| 4 |
+++ b/ggml/src/ggml-cpu/ggml-cpu.c
|
| 5 |
@@ -35,6 +35,49 @@
|
|
|
|
| 1 |
diff --git a/ggml/src/ggml-cpu/ggml-cpu.c b/ggml/src/ggml-cpu/ggml-cpu.c
|
| 2 |
+
index 53d39d2..02889fd 100644
|
| 3 |
--- a/ggml/src/ggml-cpu/ggml-cpu.c
|
| 4 |
+++ b/ggml/src/ggml-cpu/ggml-cpu.c
|
| 5 |
@@ -35,6 +35,49 @@
|