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"
Upload folder using huggingface_hub
Browse files- README.md +15 -0
- benchmarks/kld_final.log +80 -0
- benchmarks/summary.md +14 -0
- build.sh +4 -0
- machine.txt +6 -0
- patches/BASE_COMMIT +1 -0
- patches/flint-cpu-opt.patch +513 -0
- patches/optional-profiler.patch +78 -0
README.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# flint CPU optimization
|
| 2 |
+
|
| 3 |
+
CPU-optimized build of [unsloth/flint-GGUF](https://huggingface.co/unsloth/flint-GGUF) (flint-UD-Q4_K_XL.gguf) using a llama.cpp CPU patch in the style of [HelloSun/Qwen3.6-35B-A3B-GGUF_CPU_OPT](https://huggingface.co/HelloSun/Qwen3.6-35B-A3B-GGUF_CPU_OPT).
|
| 4 |
+
|
| 5 |
+
## Apply
|
| 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 |
+
## Results
|
| 15 |
+
See benchmarks/summary.md. Mean KLD vs stock: 0.2058.
|
benchmarks/kld_final.log
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
0.01.766.660 I cmn init: llama threadpool init, n_threads = 16
|
| 2 |
+
0.01.845.751 I
|
| 3 |
+
0.01.845.855 I system_info: n_threads = 16 (n_threads_batch = 16) / 192 | CPU : SSE3 = 1 | SSSE3 = 1 | AVX = 1 | AVX_VNNI = 1 | AVX2 = 1 | F16C = 1 | FMA = 1 | BMI2 = 1 | AVX512 = 1 | AVX512_VBMI = 1 | AVX512_VNNI = 1 | AVX512_BF16 = 1 | AMX_INT8 = 1 | LLAMAFILE = 1 | OPENMP = 1 | REPACK = 1 |
|
| 4 |
+
0.01.886.689 I kl_divergence: computing over 32 chunks, n_ctx=512, batch_size=512, n_seq=1
|
| 5 |
+
0.04.588.983 I kl_divergence: 2.70 seconds per pass - ETA 1.43 minutes
|
| 6 |
+
|
| 7 |
+
chunk PPL ln(PPL(Q)/PPL(base)) KL Divergence Δp RMS Same top p
|
| 8 |
+
1 31.8950 ± 10.7913 -0.01919 ± 0.12414 0.47995 ± 0.07714 16.215 ± 2.303 % 78.824 ± 2.564 %
|
| 9 |
+
2 18.7693 ± 3.8844 0.00294 ± 0.06270 0.25980 ± 0.04020 12.069 ± 1.576 % 85.294 ± 1.570 %
|
| 10 |
+
3 15.4713 ± 2.4439 0.01637 ± 0.04302 0.21289 ± 0.03283 11.207 ± 1.271 % 87.712 ± 1.188 %
|
| 11 |
+
4 14.1940 ± 1.9658 0.03541 ± 0.03515 0.22116 ± 0.02998 10.684 ± 1.035 % 88.431 ± 1.002 %
|
| 12 |
+
5 10.8930 ± 1.3155 0.01565 ± 0.03140 0.23288 ± 0.02782 11.670 ± 0.962 % 89.020 ± 0.876 %
|
| 13 |
+
6 7.3329 ± 0.7564 0.01319 ± 0.02617 0.19435 ± 0.02328 10.668 ± 0.879 % 90.850 ± 0.737 %
|
| 14 |
+
7 5.5187 ± 0.4963 0.01079 ± 0.02243 0.16887 ± 0.02007 9.970 ± 0.809 % 92.157 ± 0.637 %
|
| 15 |
+
8 4.4589 ± 0.3553 0.00925 ± 0.01963 0.14834 ± 0.01760 9.372 ± 0.755 % 93.088 ± 0.562 %
|
| 16 |
+
9 4.0899 ± 0.2965 0.00299 ± 0.01793 0.14117 ± 0.01709 9.272 ± 0.730 % 93.595 ± 0.511 %
|
| 17 |
+
10 4.9979 ± 0.3706 0.01408 ± 0.02749 0.25037 ± 0.02457 10.943 ± 0.721 % 91.647 ± 0.548 %
|
| 18 |
+
11 4.5721 ± 0.3136 0.01320 ± 0.02500 0.22823 ± 0.02238 10.458 ± 0.686 % 92.228 ± 0.506 %
|
| 19 |
+
12 4.1937 ± 0.2670 0.01381 ± 0.02296 0.21160 ± 0.02057 10.275 ± 0.655 % 92.647 ± 0.472 %
|
| 20 |
+
13 3.9080 ± 0.2322 0.01163 ± 0.02146 0.20177 ± 0.01926 10.305 ± 0.634 % 93.032 ± 0.442 %
|
| 21 |
+
14 3.7166 ± 0.2082 0.01202 ± 0.01996 0.18824 ± 0.01791 10.031 ± 0.610 % 93.389 ± 0.416 %
|
| 22 |
+
15 3.5969 ± 0.1918 0.01192 ± 0.01865 0.17664 ± 0.01673 9.818 ± 0.585 % 93.725 ± 0.392 %
|
| 23 |
+
16 3.6195 ± 0.1845 0.00955 ± 0.01752 0.16778 ± 0.01571 9.655 ± 0.562 % 93.775 ± 0.378 %
|
| 24 |
+
17 3.7784 ± 0.1872 0.00322 ± 0.01773 0.19185 ± 0.01589 10.467 ± 0.555 % 93.218 ± 0.382 %
|
| 25 |
+
18 3.9020 ± 0.1906 0.01415 ± 0.01814 0.22527 ± 0.01680 11.350 ± 0.545 % 92.702 ± 0.384 %
|
| 26 |
+
19 3.9563 ± 0.1872 0.01320 ± 0.01723 0.21543 ± 0.01595 11.213 ± 0.531 % 92.859 ± 0.370 %
|
| 27 |
+
20 4.0206 ± 0.1852 0.00258 ± 0.01733 0.22077 ± 0.01576 11.437 ± 0.520 % 92.647 ± 0.366 %
|
| 28 |
+
21 4.2279 ± 0.1948 0.01021 ± 0.01782 0.25106 ± 0.01716 12.200 ± 0.521 % 92.176 ± 0.367 %
|
| 29 |
+
22 4.2137 ± 0.1895 0.01000 ± 0.01712 0.24988 ± 0.01667 12.241 ± 0.508 % 92.103 ± 0.360 %
|
| 30 |
+
23 4.1466 ± 0.1817 0.01604 ± 0.01705 0.24787 ± 0.01625 12.207 ± 0.495 % 92.242 ± 0.349 %
|
| 31 |
+
24 4.1800 ± 0.1779 0.01373 ± 0.01640 0.23897 ± 0.01559 11.969 ± 0.484 % 92.435 ± 0.338 %
|
| 32 |
+
25 4.1542 ± 0.1722 0.01618 ± 0.01584 0.23559 ± 0.01505 12.003 ± 0.474 % 92.502 ± 0.330 %
|
| 33 |
+
26 4.0994 ± 0.1649 0.01558 ± 0.01527 0.22948 ± 0.01454 11.892 ± 0.466 % 92.609 ± 0.321 %
|
| 34 |
+
27 4.1120 ± 0.1618 0.01565 ± 0.01479 0.22470 ± 0.01405 11.881 ± 0.458 % 92.694 ± 0.314 %
|
| 35 |
+
28 4.2240 ± 0.1640 0.01531 ± 0.01436 0.22426 ± 0.01375 11.893 ± 0.449 % 92.591 ± 0.310 %
|
| 36 |
+
29 4.2403 ± 0.1614 0.01391 ± 0.01395 0.22072 ± 0.01336 11.775 ± 0.440 % 92.630 ± 0.304 %
|
| 37 |
+
30 4.2686 ± 0.1591 0.01269 ± 0.01350 0.21384 ± 0.01292 11.600 ± 0.432 % 92.745 ± 0.297 %
|
| 38 |
+
31 4.2673 ± 0.1558 0.01106 ± 0.01308 0.20801 ± 0.01252 11.505 ± 0.425 % 92.865 ± 0.290 %
|
| 39 |
+
32 4.1299 ± 0.1470 0.01347 ± 0.01282 0.20576 ± 0.01230 11.498 ± 0.420 % 92.990 ± 0.283 %
|
| 40 |
+
|
| 41 |
+
====== Perplexity statistics ======
|
| 42 |
+
Mean PPL(Q) : 4.129912 ± 0.147024
|
| 43 |
+
Mean PPL(base) : 4.074668 ± 0.139399
|
| 44 |
+
Cor(ln(PPL(Q)), ln(PPL(base))): 93.34%
|
| 45 |
+
Mean ln(PPL(Q)/PPL(base)) : 0.013467 ± 0.012816
|
| 46 |
+
Mean PPL(Q)/PPL(base) : 1.013558 ± 0.012990
|
| 47 |
+
Mean PPL(Q)-PPL(base) : 0.055243 ± 0.052818
|
| 48 |
+
|
| 49 |
+
====== KL divergence statistics ======
|
| 50 |
+
Mean KLD: 0.205759 ± 0.012297
|
| 51 |
+
Maximum KLD: 20.963177
|
| 52 |
+
99.9% KLD: 14.032636
|
| 53 |
+
99.0% KLD: 5.719375
|
| 54 |
+
95.0% KLD: 0.771354
|
| 55 |
+
90.0% KLD: 0.092588
|
| 56 |
+
Median KLD: 0.000773
|
| 57 |
+
10.0% KLD: 0.000002
|
| 58 |
+
5.0% KLD: 0.000000
|
| 59 |
+
1.0% KLD: -0.000000
|
| 60 |
+
0.1% KLD: -0.000001
|
| 61 |
+
Minimum KLD: -0.000013
|
| 62 |
+
|
| 63 |
+
====== Token probability statistics ======
|
| 64 |
+
Mean Δp: -0.023 ± 0.127 %
|
| 65 |
+
Maximum Δp: 99.114%
|
| 66 |
+
99.9% Δp: 96.666%
|
| 67 |
+
99.0% Δp: 42.103%
|
| 68 |
+
95.0% Δp: 4.663%
|
| 69 |
+
90.0% Δp: 1.578%
|
| 70 |
+
75.0% Δp: 0.070%
|
| 71 |
+
Median Δp: -0.000%
|
| 72 |
+
25.0% Δp: -0.066%
|
| 73 |
+
10.0% Δp: -1.639%
|
| 74 |
+
5.0% Δp: -5.594%
|
| 75 |
+
1.0% Δp: -38.947%
|
| 76 |
+
0.1% Δp: -98.266%
|
| 77 |
+
Minimum Δp: -99.912%
|
| 78 |
+
RMS Δp : 11.498 ± 0.420 %
|
| 79 |
+
Same top p: 92.990 ± 0.283 %
|
| 80 |
+
|
benchmarks/summary.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# flint CPU optimization benchmarks
|
| 2 |
+
|
| 3 |
+
Model: unsloth/flint-GGUF flint-UD-Q4_K_XL.gguf (25.05 GiB)
|
| 4 |
+
Hardware: Intel Xeon Platinum 8559C, 16 threads, taskset -c 0-15, -fa 1
|
| 5 |
+
|
| 6 |
+
| metric | stock (t/s) | optimized (t/s) | speedup |
|
| 7 |
+
|---|---|---|---|
|
| 8 |
+
| pp256 | 221.5 | 260.9 | 1.15x |
|
| 9 |
+
| tg128 | 32.6 | 35.4 | 1.07x |
|
| 10 |
+
| pp2048 | 215.4 | 263.4 | 1.22x |
|
| 11 |
+
| tg128 (pp2048 run) | 32.9 | 37.3 | 1.13x |
|
| 12 |
+
|
| 13 |
+
Mean KLD vs stock: 0.2058 ± 0.0123 (prefill+decode, 32 chunks x 512)
|
| 14 |
+
Mean PPL(Q)/PPL(base): 1.0136
|
build.sh
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 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-bench llama-cli llama-perplexity
|
machine.txt
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
CPU: Intel Xeon Platinum 8559C (Emerald Rapids)
|
| 2 |
+
Threads used: 16 (cgroup cpu.max 1600000/100000)
|
| 3 |
+
Memory cap: ~104 GiB (cgroup memory.max)
|
| 4 |
+
Build: GCC 14.2.0, cmake 3.31.6, -march=native (AVX512, VNNI, AMX-INT8)
|
| 5 |
+
llama.cpp base commit: 338fce651 (b11942)
|
| 6 |
+
AMX buffer: 1716 MiB (Q8_0 2D tensors); CPU_REPACK: 864 MiB (Q4_K 8x8)
|
patches/BASE_COMMIT
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
338fce6511c744893cc0d3d958b275f40552c7a4
|
patches/flint-cpu-opt.patch
ADDED
|
@@ -0,0 +1,513 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
| 4 |
+
+++ b/ggml/src/ggml-cpu/amx/amx.cpp
|
| 5 |
+
@@ -161,6 +161,17 @@ class extra_buffer_type : ggml::cpu::extra_buffer_type {
|
| 6 |
+
if (op->ne[0] % (TILE_N * 2)) {
|
| 7 |
+
return false;
|
| 8 |
+
}
|
| 9 |
+
+ // machine-specific knobs: keep selected types out of the AMX buffer (decode then uses the VNNI vec_dot kernels)
|
| 10 |
+
+ {
|
| 11 |
+
+ // Q6_K (lm_head): the AVX512-VNNI vec_dot is ~9% faster for decode than the AMX M=1 kernel; opt back in with GGML_AMX_Q6K=1
|
| 12 |
+
+ static const char * keep_q6 = getenv("GGML_AMX_Q6K");
|
| 13 |
+
+ if (src0->type == GGML_TYPE_Q6_K && !(keep_q6 && keep_q6[0] == '1')) { return false; }
|
| 14 |
+
+ static const char * skip = getenv("GGML_AMX_SKIP");
|
| 15 |
+
+ if (skip) {
|
| 16 |
+
+ if (src0->type == GGML_TYPE_Q6_K && strstr(skip, "q6_K")) { return false; }
|
| 17 |
+
+ if (src0->type == GGML_TYPE_Q8_0 && strstr(skip, "q8_0")) { return false; }
|
| 18 |
+
+ }
|
| 19 |
+
+ }
|
| 20 |
+
int alignment;
|
| 21 |
+
switch (src0->type) {
|
| 22 |
+
case GGML_TYPE_Q4_0:
|
| 23 |
+
diff --git a/ggml/src/ggml-cpu/amx/mmq.cpp b/ggml/src/ggml-cpu/amx/mmq.cpp
|
| 24 |
+
index 9f3a744b5..d23e4d971 100644
|
| 25 |
+
--- a/ggml/src/ggml-cpu/amx/mmq.cpp
|
| 26 |
+
+++ b/ggml/src/ggml-cpu/amx/mmq.cpp
|
| 27 |
+
@@ -1989,6 +1989,91 @@ struct tinygemm_kernel_vnni<block_q8_K, block_iq4_xs, float, BLOCK_M, BLOCK_N, B
|
| 28 |
+
(const char *)src0->data + src0_offset + PACKED_INDEX(nb * kTilesN, 0, KB, TILE_SIZE), \
|
| 29 |
+
(float *) dst->data + dst_offset + nb_start, ldc)
|
| 30 |
+
|
| 31 |
+
+// Q8_0 x Q8_0 AMX gemm with register accumulation: one 16x16 output tile at a time, its 16 float row
|
| 32 |
+
+// accumulators live in zmm registers across all K blocks (the generic kernel read-modify-writes C through memory
|
| 33 |
+
+// every 32-wide K block and converts the A scale per row). The AMX product of block i+1 is issued before the AVX
|
| 34 |
+
+// epilogue of block i so the two overlap. Per-block math (cvt(int32) * (dW*dA) accumulated with an fma, blocks in
|
| 35 |
+
+// order) is identical to acc_C, so results are bit-identical. Returns false when KB is too large for the scale cache.
|
| 36 |
+
+// tile registers are pasted into the asm string by the intrinsics, so they must be literals: one function per slot
|
| 37 |
+
+#define Q8_REGACC_ISSUE_FN(NAME, TB_, TA_, TC_, SLOT) \
|
| 38 |
+
+static ALWAYS_INLINE void NAME(const block_q8_0 * RESTRICT A, const char * RESTRICT B, int KB, int u, int t, \
|
| 39 |
+
+ int mrows, int i, int8_t (*TileA)[TILE_M * TILE_K], int32_t (*TileC)[TILE_M * TILE_N]) { \
|
| 40 |
+
+ const int TILE_SIZE = get_tile_size<block_q8_0>(); /* 16 x 34 B + 16 x int32 compensation */ \
|
| 41 |
+
+ const char * Bb = B + PACKED_INDEX(t, i, KB, TILE_SIZE); \
|
| 42 |
+
+ _tile_loadd(TB_, Bb, TILE_N * VNNI_BLK); \
|
| 43 |
+
+ const block_q8_0 * Ab = A + (size_t) (u * TILE_M) * KB + i; \
|
| 44 |
+
+ if (mrows == TILE_M) { \
|
| 45 |
+
+ _tile_loadd(TA_, Ab->qs, KB * sizeof(block_q8_0)); \
|
| 46 |
+
+ } else { \
|
| 47 |
+
+ unpack_A(TileA[SLOT], Ab, KB, mrows); \
|
| 48 |
+
+ _tile_loadd(TA_, TileA[SLOT], TILE_K); \
|
| 49 |
+
+ } \
|
| 50 |
+
+ _tile_zero(TC_); \
|
| 51 |
+
+ _tile_dpbssd(TC_, TA_, TB_); \
|
| 52 |
+
+ _tile_stored(TC_, TileC[SLOT], TILE_N * sizeof(int32_t)); \
|
| 53 |
+
+}
|
| 54 |
+
+Q8_REGACC_ISSUE_FN(q8_regacc_issue0, 0, 2, 4, 0)
|
| 55 |
+
+Q8_REGACC_ISSUE_FN(q8_regacc_issue1, 1, 3, 5, 1)
|
| 56 |
+
+#undef Q8_REGACC_ISSUE_FN
|
| 57 |
+
+
|
| 58 |
+
+static bool tinygemm_kernel_amx_q8_0_regacc(int M, int KB, const block_q8_0 * RESTRICT A, const char * RESTRICT B,
|
| 59 |
+
+ float * RESTRICT C, int ldc) {
|
| 60 |
+
+ constexpr int MAX_KB = 256;
|
| 61 |
+
+ if (KB > MAX_KB || KB < 1) {
|
| 62 |
+
+ return false;
|
| 63 |
+
+ }
|
| 64 |
+
+ const int TILE_SIZE = get_tile_size<block_q8_0>(); /* 16 x 34 B + 16 x int32 compensation */
|
| 65 |
+
+ constexpr int SCALE_OFF = TILE_N * TILE_K;
|
| 66 |
+
+
|
| 67 |
+
+ alignas(64) static thread_local int8_t TileA[2][TILE_M * TILE_K];
|
| 68 |
+
+ alignas(64) static thread_local int32_t TileC[2][TILE_M * TILE_N];
|
| 69 |
+
+ alignas(64) static thread_local float sA[2 * TILE_M][MAX_KB];
|
| 70 |
+
+
|
| 71 |
+
+ const int rows = std::min(M, 2 * TILE_M);
|
| 72 |
+
+ for (int r = 0; r < 2 * TILE_M; ++r) {
|
| 73 |
+
+ for (int i = 0; i < KB; ++i) {
|
| 74 |
+
+ sA[r][i] = r < rows ? GGML_CPU_FP16_TO_FP32(A[(size_t) r * KB + i].d) : 0.0f;
|
| 75 |
+
+ }
|
| 76 |
+
+ }
|
| 77 |
+
+
|
| 78 |
+
+ const int nu = rows > TILE_M ? 2 : 1;
|
| 79 |
+
+ for (int u = 0; u < nu; ++u) {
|
| 80 |
+
+ const int mrows = std::min(TILE_M, rows - u * TILE_M);
|
| 81 |
+
+ for (int t = 0; t < 2; ++t) {
|
| 82 |
+
+ __m512 acc[TILE_M];
|
| 83 |
+
+ #pragma GCC unroll 16
|
| 84 |
+
+ for (int m = 0; m < TILE_M; ++m) {
|
| 85 |
+
+ acc[m] = _mm512_setzero_ps();
|
| 86 |
+
+ }
|
| 87 |
+
+
|
| 88 |
+
+ q8_regacc_issue0(A, B, KB, u, t, mrows, 0, TileA, TileC);
|
| 89 |
+
+ for (int i = 0; i < KB; ++i) {
|
| 90 |
+
+ const int slot = i & 1;
|
| 91 |
+
+ if (i + 1 < KB) {
|
| 92 |
+
+ if (slot == 0) {
|
| 93 |
+
+ q8_regacc_issue1(A, B, KB, u, t, mrows, i + 1, TileA, TileC);
|
| 94 |
+
+ } else {
|
| 95 |
+
+ q8_regacc_issue0(A, B, KB, u, t, mrows, i + 1, TileA, TileC);
|
| 96 |
+
+ }
|
| 97 |
+
+ }
|
| 98 |
+
+ const __m512 vd0 = _mm512_cvtph_ps(_mm256_loadu_si256((const __m256i *) (B + PACKED_INDEX(t, i, KB, TILE_SIZE) + SCALE_OFF)));
|
| 99 |
+
+ const int32_t * tile = TileC[slot];
|
| 100 |
+
+ const float * sa = &sA[u * TILE_M][0];
|
| 101 |
+
+ #pragma GCC unroll 16
|
| 102 |
+
+ for (int m = 0; m < TILE_M; ++m) {
|
| 103 |
+
+ const __m512 vtile = _mm512_cvtepi32_ps(_mm512_loadu_si512(tile + m * TILE_N));
|
| 104 |
+
+ const __m512 vd1 = _mm512_set1_ps(sa[(size_t) m * MAX_KB + i]);
|
| 105 |
+
+ acc[m] = _mm512_fmadd_ps(vtile, _mm512_mul_ps(vd0, vd1), acc[m]);
|
| 106 |
+
+ }
|
| 107 |
+
+ }
|
| 108 |
+
+ for (int m = 0; m < mrows; ++m) {
|
| 109 |
+
+ _mm512_storeu_ps(C + (size_t) (u * TILE_M + m) * ldc + t * TILE_N, acc[m]);
|
| 110 |
+
+ }
|
| 111 |
+
+ }
|
| 112 |
+
+ }
|
| 113 |
+
+ return true;
|
| 114 |
+
+}
|
| 115 |
+
+
|
| 116 |
+
template <typename TA, typename TB, typename TC, int BLOCK_K,
|
| 117 |
+
typename std::enable_if<!is_type_qkk<TB>::value, int>::type = 0>
|
| 118 |
+
void tinygemm_kernel_amx(int M, int N, int KB, const void * RESTRICT _A, const void * RESTRICT _B, TC * RESTRICT C, int ldc) {
|
| 119 |
+
@@ -1997,6 +2082,12 @@ void tinygemm_kernel_amx(int M, int N, int KB, const void * RESTRICT _A, const v
|
| 120 |
+
const bool need_unpack = do_unpack<TB>::value;
|
| 121 |
+
|
| 122 |
+
GGML_ASSERT(M <= 2 * TILE_M && N == 2 * TILE_N);
|
| 123 |
+
+ if constexpr (std::is_same<TB, block_q8_0>::value && std::is_same<TA, block_q8_0>::value) {
|
| 124 |
+
+ static const bool regacc = [] { const char * e = getenv("GGML_AMX_Q8_REGACC"); return !(e && e[0] == '0'); }();
|
| 125 |
+
+ if (regacc && tinygemm_kernel_amx_q8_0_regacc(M, KB, static_cast<const block_q8_0 *>(_A), static_cast<const char *>(_B), C, ldc)) {
|
| 126 |
+
+ return;
|
| 127 |
+
+ }
|
| 128 |
+
+ }
|
| 129 |
+
const TA * RESTRICT A = static_cast<const TA *>(_A);
|
| 130 |
+
const char * RESTRICT B = static_cast<const char *>(_B);
|
| 131 |
+
|
| 132 |
+
@@ -2434,8 +2525,9 @@ void ggml_backend_amx_mul_mat(const ggml_compute_params * params, struct ggml_te
|
| 133 |
+
|
| 134 |
+
if (M == 1) {
|
| 135 |
+
// MB = 1 and handle 8 tiles in each block
|
| 136 |
+
- constexpr int kTilesN = 4;
|
| 137 |
+
- constexpr int BLOCK_N = TILE_N * kTilesN;
|
| 138 |
+
+ // small N (e.g. 512) would give fewer tasks than threads with 64-wide blocks; use 32-wide blocks
|
| 139 |
+
+ const int BLOCK_N = (N <= 1024) ? 32 : 64;
|
| 140 |
+
+ const int kTilesN = BLOCK_N / TILE_N;
|
| 141 |
+
const int NB = div_up(N, BLOCK_N);
|
| 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..0e8aafa76 100644
|
| 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
|
| 149 |
+
|
| 150 |
+
uint32_t utmp[4];
|
| 151 |
+
|
| 152 |
+
-#if defined __AVX2__
|
| 153 |
+
+#if defined(__AVX512F__) && defined(__AVX512BW__) && defined(__AVX512VL__) && defined(__AVX512VNNI__)
|
| 154 |
+
+ // AVX512-VNNI path (Q4_K x Q8_K): 64 weights per vector, two 32-wide sub-blocks per vector.
|
| 155 |
+
+ const __m512i m4 = _mm512_set1_epi8(0xF);
|
| 156 |
+
+ #define K4_SCALE_IDX(a, b) _mm512_inserti64x4( \
|
| 157 |
+
+ _mm512_castsi256_si512(_mm256_set_m128i(_mm_set1_epi16((short)((2*(a)) | ((2*(a)+1) << 8))), _mm_set1_epi16((short)((2*(a)) | ((2*(a)+1) << 8))))), \
|
| 158 |
+
+ _mm256_set_m128i(_mm_set1_epi16((short)((2*(b)) | ((2*(b)+1) << 8))), _mm_set1_epi16((short)((2*(b)) | ((2*(b)+1) << 8)))), 1)
|
| 159 |
+
+ const __m512i sidx0 = K4_SCALE_IDX(0, 2);
|
| 160 |
+
+ const __m512i sidx1 = K4_SCALE_IDX(1, 3);
|
| 161 |
+
+ const __m512i sidx2 = K4_SCALE_IDX(4, 6);
|
| 162 |
+
+ const __m512i sidx3 = K4_SCALE_IDX(5, 7);
|
| 163 |
+
+ #undef K4_SCALE_IDX
|
| 164 |
+
+
|
| 165 |
+
+ __m512 acc = _mm512_setzero_ps();
|
| 166 |
+
+ __m128 acc_m = _mm_setzero_ps();
|
| 167 |
+
+
|
| 168 |
+
+ for (int i = 0; i < nb; ++i) {
|
| 169 |
+
+#ifndef K4_PF_DIST
|
| 170 |
+
+#define K4_PF_DIST 40 // ~9 KB ahead, tuned for Xeon 8559C (prefetch into L2)
|
| 171 |
+
+#endif
|
| 172 |
+
+ static int k4pf = -1;
|
| 173 |
+
+ if (k4pf < 0) { const char * e = getenv("GGML_K4_PF"); k4pf = e ? atoi(e) : K4_PF_DIST; }
|
| 174 |
+
+ {
|
| 175 |
+
+ const char * pf = (const char *)(x + i + k4pf);
|
| 176 |
+
+ _mm_prefetch(pf, _MM_HINT_T1);
|
| 177 |
+
+ _mm_prefetch(pf + 64, _MM_HINT_T1);
|
| 178 |
+
+ _mm_prefetch(pf + 128, _MM_HINT_T1);
|
| 179 |
+
+ }
|
| 180 |
+
+
|
| 181 |
+
+ const float d = y[i].d * GGML_CPU_FP16_TO_FP32(x[i].d);
|
| 182 |
+
+ const float dmin = -y[i].d * GGML_CPU_FP16_TO_FP32(x[i].dmin);
|
| 183 |
+
+
|
| 184 |
+
+ memcpy(utmp, x[i].scales, 12);
|
| 185 |
+
+ utmp[3] = ((utmp[2] >> 4) & kmask2) | (((utmp[1] >> 6) & kmask3) << 4);
|
| 186 |
+
+ const uint32_t uaux = utmp[1] & kmask1;
|
| 187 |
+
+ utmp[1] = (utmp[2] & kmask2) | (((utmp[0] >> 6) & kmask3) << 4);
|
| 188 |
+
+ utmp[2] = uaux;
|
| 189 |
+
+ utmp[0] &= kmask1;
|
| 190 |
+
+
|
| 191 |
+
+ const uint8_t * GGML_RESTRICT q4 = x[i].qs;
|
| 192 |
+
+ const int8_t * GGML_RESTRICT q8 = y[i].qs;
|
| 193 |
+
+
|
| 194 |
+
+ const __m256i mins_and_scales = _mm256_cvtepu8_epi16(_mm_set_epi32(utmp[3], utmp[2], utmp[1], utmp[0]));
|
| 195 |
+
+
|
| 196 |
+
+ const __m256i q8sums = _mm256_loadu_si256((const __m256i*)y[i].bsums);
|
| 197 |
+
+ const __m128i q8s = _mm_hadd_epi16(_mm256_extracti128_si256(q8sums, 0), _mm256_extracti128_si256(q8sums, 1));
|
| 198 |
+
+ const __m128i prod = _mm_madd_epi16(_mm256_extracti128_si256(mins_and_scales, 1), q8s);
|
| 199 |
+
+ acc_m = _mm_fmadd_ps(_mm_set1_ps(dmin), _mm_cvtepi32_ps(prod), acc_m);
|
| 200 |
+
+
|
| 201 |
+
+ const __m512i scales = _mm512_broadcast_i32x4(_mm256_extracti128_si256(mins_and_scales, 0));
|
| 202 |
+
+
|
| 203 |
+
+ const __m512i v0 = _mm512_loadu_si512((const void *)(q4));
|
| 204 |
+
+ const __m512i v1 = _mm512_loadu_si512((const void *)(q4 + 64));
|
| 205 |
+
+
|
| 206 |
+
+ const __m512i Q0 = _mm512_loadu_si512((const void *)(q8));
|
| 207 |
+
+ const __m512i Q1 = _mm512_loadu_si512((const void *)(q8 + 64));
|
| 208 |
+
+ const __m512i Q2 = _mm512_loadu_si512((const void *)(q8 + 128));
|
| 209 |
+
+ const __m512i Q3 = _mm512_loadu_si512((const void *)(q8 + 192));
|
| 210 |
+
+
|
| 211 |
+
+ const __m512i a0 = _mm512_and_si512(v0, m4);
|
| 212 |
+
+ const __m512i a1 = _mm512_and_si512(_mm512_srli_epi16(v0, 4), m4);
|
| 213 |
+
+ const __m512i a2 = _mm512_and_si512(v1, m4);
|
| 214 |
+
+ const __m512i a3 = _mm512_and_si512(_mm512_srli_epi16(v1, 4), m4);
|
| 215 |
+
+
|
| 216 |
+
+ const __m512i b0 = _mm512_shuffle_i64x2(Q0, Q1, 0x44);
|
| 217 |
+
+ const __m512i b1 = _mm512_shuffle_i64x2(Q0, Q1, 0xEE);
|
| 218 |
+
+ const __m512i b2 = _mm512_shuffle_i64x2(Q2, Q3, 0x44);
|
| 219 |
+
+ const __m512i b3 = _mm512_shuffle_i64x2(Q2, Q3, 0xEE);
|
| 220 |
+
+
|
| 221 |
+
+ __m512i sumi = _mm512_setzero_si512();
|
| 222 |
+
+ sumi = _mm512_dpwssd_epi32(sumi, _mm512_maddubs_epi16(a0, b0), _mm512_shuffle_epi8(scales, sidx0));
|
| 223 |
+
+ sumi = _mm512_dpwssd_epi32(sumi, _mm512_maddubs_epi16(a1, b1), _mm512_shuffle_epi8(scales, sidx1));
|
| 224 |
+
+ sumi = _mm512_dpwssd_epi32(sumi, _mm512_maddubs_epi16(a2, b2), _mm512_shuffle_epi8(scales, sidx2));
|
| 225 |
+
+ sumi = _mm512_dpwssd_epi32(sumi, _mm512_maddubs_epi16(a3, b3), _mm512_shuffle_epi8(scales, sidx3));
|
| 226 |
+
+
|
| 227 |
+
+ acc = _mm512_fmadd_ps(_mm512_set1_ps(d), _mm512_cvtepi32_ps(sumi), acc);
|
| 228 |
+
+ }
|
| 229 |
+
+
|
| 230 |
+
+ acc_m = _mm_add_ps(acc_m, _mm_movehl_ps(acc_m, acc_m));
|
| 231 |
+
+ acc_m = _mm_add_ss(acc_m, _mm_movehdup_ps(acc_m));
|
| 232 |
+
+
|
| 233 |
+
+ *s = _mm512_reduce_add_ps(acc) + _mm_cvtss_f32(acc_m);
|
| 234 |
+
+
|
| 235 |
+
+#elif defined __AVX2__
|
| 236 |
+
|
| 237 |
+
const __m256i m4 = _mm256_set1_epi8(0xF);
|
| 238 |
+
|
| 239 |
+
@@ -2296,7 +2378,97 @@ void ggml_vec_dot_q5_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const voi
|
| 240 |
+
|
| 241 |
+
uint32_t utmp[4];
|
| 242 |
+
|
| 243 |
+
-#if defined __AVX2__
|
| 244 |
+
+#if defined(__AVX512F__) && defined(__AVX512BW__) && defined(__AVX512VL__) && defined(__AVX512VNNI__)
|
| 245 |
+
+ // AVX512-VNNI path (Q5_K x Q8_K), same structure as the Q4_K kernel: 64 weights per vector, two 32-wide
|
| 246 |
+
+ // sub-blocks per vector. The 5th bit of sub-block s is bit s of qh[l]; it is merged in as +16 before maddubs.
|
| 247 |
+
+ const __m512i m4 = _mm512_set1_epi8(0xF);
|
| 248 |
+
+ const __m512i m10 = _mm512_set1_epi8(0x10);
|
| 249 |
+
+ #define K5_SCALE_IDX(a, b) _mm512_inserti64x4( \
|
| 250 |
+
+ _mm512_castsi256_si512(_mm256_set_m128i(_mm_set1_epi16((short)((2*(a)) | ((2*(a)+1) << 8))), _mm_set1_epi16((short)((2*(a)) | ((2*(a)+1) << 8))))), \
|
| 251 |
+
+ _mm256_set_m128i(_mm_set1_epi16((short)((2*(b)) | ((2*(b)+1) << 8))), _mm_set1_epi16((short)((2*(b)) | ((2*(b)+1) << 8)))), 1)
|
| 252 |
+
+ const __m512i sidx0 = K5_SCALE_IDX(0, 2);
|
| 253 |
+
+ const __m512i sidx1 = K5_SCALE_IDX(1, 3);
|
| 254 |
+
+ const __m512i sidx2 = K5_SCALE_IDX(4, 6);
|
| 255 |
+
+ const __m512i sidx3 = K5_SCALE_IDX(5, 7);
|
| 256 |
+
+ #undef K5_SCALE_IDX
|
| 257 |
+
+ #define K5_CNT(a, b) _mm512_inserti64x4(_mm512_castsi256_si512(_mm256_set1_epi16(a)), _mm256_set1_epi16(b), 1)
|
| 258 |
+
+ const __m512i cl0 = K5_CNT(4, 2); // sub-blocks 0,2 : bit s -> bit 4 via left shift 4-s
|
| 259 |
+
+ const __m512i cl1 = K5_CNT(3, 1); // sub-blocks 1,3
|
| 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; }
|
| 266 |
+
+
|
| 267 |
+
+ __m512 acc = _mm512_setzero_ps();
|
| 268 |
+
+ __m128 acc_m = _mm_setzero_ps();
|
| 269 |
+
+
|
| 270 |
+
+ for (int i = 0; i < nb; ++i) {
|
| 271 |
+
+ {
|
| 272 |
+
+ const char * pf = (const char *)(x + i + k5pf);
|
| 273 |
+
+ _mm_prefetch(pf, _MM_HINT_T1);
|
| 274 |
+
+ _mm_prefetch(pf + 64, _MM_HINT_T1);
|
| 275 |
+
+ _mm_prefetch(pf + 128, _MM_HINT_T1);
|
| 276 |
+
+ }
|
| 277 |
+
+
|
| 278 |
+
+ const float d = y[i].d * GGML_CPU_FP16_TO_FP32(x[i].d);
|
| 279 |
+
+ const float dmin = -y[i].d * GGML_CPU_FP16_TO_FP32(x[i].dmin);
|
| 280 |
+
+
|
| 281 |
+
+ memcpy(utmp, x[i].scales, 12);
|
| 282 |
+
+ utmp[3] = ((utmp[2] >> 4) & kmask2) | (((utmp[1] >> 6) & kmask3) << 4);
|
| 283 |
+
+ const uint32_t uaux = utmp[1] & kmask1;
|
| 284 |
+
+ utmp[1] = (utmp[2] & kmask2) | (((utmp[0] >> 6) & kmask3) << 4);
|
| 285 |
+
+ utmp[2] = uaux;
|
| 286 |
+
+ utmp[0] &= kmask1;
|
| 287 |
+
+
|
| 288 |
+
+ const uint8_t * GGML_RESTRICT q5 = x[i].qs;
|
| 289 |
+
+ const int8_t * GGML_RESTRICT q8 = y[i].qs;
|
| 290 |
+
+
|
| 291 |
+
+ const __m256i mins_and_scales = _mm256_cvtepu8_epi16(_mm_set_epi32(utmp[3], utmp[2], utmp[1], utmp[0]));
|
| 292 |
+
+
|
| 293 |
+
+ const __m256i q8sums = _mm256_loadu_si256((const __m256i*)y[i].bsums);
|
| 294 |
+
+ const __m128i q8s = _mm_hadd_epi16(_mm256_extracti128_si256(q8sums, 0), _mm256_extracti128_si256(q8sums, 1));
|
| 295 |
+
+ const __m128i prod = _mm_madd_epi16(_mm256_extracti128_si256(mins_and_scales, 1), q8s);
|
| 296 |
+
+ acc_m = _mm_fmadd_ps(_mm_set1_ps(dmin), _mm_cvtepi32_ps(prod), acc_m);
|
| 297 |
+
+
|
| 298 |
+
+ const __m512i scales = _mm512_broadcast_i32x4(_mm256_extracti128_si256(mins_and_scales, 0));
|
| 299 |
+
+
|
| 300 |
+
+ const __m512i qhv = _mm512_broadcast_i64x4(_mm256_loadu_si256((const __m256i *)x[i].qh));
|
| 301 |
+
+
|
| 302 |
+
+ const __m512i v0 = _mm512_loadu_si512((const void *)(q5));
|
| 303 |
+
+ const __m512i v1 = _mm512_loadu_si512((const void *)(q5 + 64));
|
| 304 |
+
+
|
| 305 |
+
+ const __m512i Q0 = _mm512_loadu_si512((const void *)(q8));
|
| 306 |
+
+ const __m512i Q1 = _mm512_loadu_si512((const void *)(q8 + 64));
|
| 307 |
+
+ const __m512i Q2 = _mm512_loadu_si512((const void *)(q8 + 128));
|
| 308 |
+
+ const __m512i Q3 = _mm512_loadu_si512((const void *)(q8 + 192));
|
| 309 |
+
+
|
| 310 |
+
+ const __m512i a0 = _mm512_or_si512(_mm512_and_si512(v0, m4), _mm512_and_si512(_mm512_sllv_epi16(qhv, cl0), m10));
|
| 311 |
+
+ const __m512i a1 = _mm512_or_si512(_mm512_and_si512(_mm512_srli_epi16(v0, 4), m4), _mm512_and_si512(_mm512_sllv_epi16(qhv, cl1), m10));
|
| 312 |
+
+ const __m512i a2 = _mm512_or_si512(_mm512_and_si512(v1, m4), _mm512_and_si512(_mm512_srlv_epi16(qhv, cr2), m10));
|
| 313 |
+
+ const __m512i a3 = _mm512_or_si512(_mm512_and_si512(_mm512_srli_epi16(v1, 4), m4), _mm512_and_si512(_mm512_srlv_epi16(qhv, cr3), m10));
|
| 314 |
+
+
|
| 315 |
+
+ const __m512i b0 = _mm512_shuffle_i64x2(Q0, Q1, 0x44);
|
| 316 |
+
+ const __m512i b1 = _mm512_shuffle_i64x2(Q0, Q1, 0xEE);
|
| 317 |
+
+ const __m512i b2 = _mm512_shuffle_i64x2(Q2, Q3, 0x44);
|
| 318 |
+
+ const __m512i b3 = _mm512_shuffle_i64x2(Q2, Q3, 0xEE);
|
| 319 |
+
+
|
| 320 |
+
+ __m512i sumi = _mm512_setzero_si512();
|
| 321 |
+
+ sumi = _mm512_dpwssd_epi32(sumi, _mm512_maddubs_epi16(a0, b0), _mm512_shuffle_epi8(scales, sidx0));
|
| 322 |
+
+ sumi = _mm512_dpwssd_epi32(sumi, _mm512_maddubs_epi16(a1, b1), _mm512_shuffle_epi8(scales, sidx1));
|
| 323 |
+
+ sumi = _mm512_dpwssd_epi32(sumi, _mm512_maddubs_epi16(a2, b2), _mm512_shuffle_epi8(scales, sidx2));
|
| 324 |
+
+ sumi = _mm512_dpwssd_epi32(sumi, _mm512_maddubs_epi16(a3, b3), _mm512_shuffle_epi8(scales, sidx3));
|
| 325 |
+
+
|
| 326 |
+
+ acc = _mm512_fmadd_ps(_mm512_set1_ps(d), _mm512_cvtepi32_ps(sumi), acc);
|
| 327 |
+
+ }
|
| 328 |
+
+
|
| 329 |
+
+ acc_m = _mm_add_ps(acc_m, _mm_movehl_ps(acc_m, acc_m));
|
| 330 |
+
+ acc_m = _mm_add_ss(acc_m, _mm_movehdup_ps(acc_m));
|
| 331 |
+
+
|
| 332 |
+
+ *s = _mm512_reduce_add_ps(acc) + _mm_cvtss_f32(acc_m);
|
| 333 |
+
+
|
| 334 |
+
+#elif defined __AVX2__
|
| 335 |
+
|
| 336 |
+
const __m256i m4 = _mm256_set1_epi8(0xF);
|
| 337 |
+
const __m128i mzero = _mm_setzero_si128();
|
| 338 |
+
@@ -2500,7 +2672,81 @@ void ggml_vec_dot_q6_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const voi
|
| 339 |
+
|
| 340 |
+
const int nb = n / QK_K;
|
| 341 |
+
|
| 342 |
+
-#if defined __AVX2__
|
| 343 |
+
+#if defined(__AVX512F__) && defined(__AVX512BW__) && defined(__AVX512VL__) && defined(__AVX512VNNI__)
|
| 344 |
+
+ // AVX512-VNNI path (Q6_K x Q8_K): each 64-byte vector holds two 32-wide chunks.
|
| 345 |
+
+ const __m512i m15 = _mm512_set1_epi8(0xF);
|
| 346 |
+
+ const __m512i m30 = _mm512_set1_epi8(0x30);
|
| 347 |
+
+ const __m512i shl_cnt = _mm512_inserti64x4(_mm512_castsi256_si512(_mm256_set1_epi16(4)), _mm256_set1_epi16(2), 1);
|
| 348 |
+
+ const __m512i shr_cnt = _mm512_inserti64x4(_mm512_castsi256_si512(_mm256_set1_epi16(0)), _mm256_set1_epi16(2), 1);
|
| 349 |
+
+ #define Q6_SIDX(c1, c2) _mm512_inserti64x4( \
|
| 350 |
+
+ _mm512_castsi256_si512(_mm256_set_m128i(_mm_set1_epi16((short)(2*(c1)+1)), _mm_set1_epi16((short)(2*(c1))))), \
|
| 351 |
+
+ _mm256_set_m128i(_mm_set1_epi16((short)(2*(c2)+1)), _mm_set1_epi16((short)(2*(c2)))), 1)
|
| 352 |
+
+ const __m512i sidx0 = Q6_SIDX(0, 1);
|
| 353 |
+
+ const __m512i sidx1 = Q6_SIDX(2, 3);
|
| 354 |
+
+ const __m512i sidx2 = Q6_SIDX(4, 5);
|
| 355 |
+
+ const __m512i sidx3 = Q6_SIDX(6, 7);
|
| 356 |
+
+ #undef Q6_SIDX
|
| 357 |
+
+
|
| 358 |
+
+ __m512 acc = _mm512_setzero_ps();
|
| 359 |
+
+
|
| 360 |
+
+ for (int i = 0; i < nb; ++i) {
|
| 361 |
+
+#ifndef Q6_PF_DIST
|
| 362 |
+
+#define Q6_PF_DIST 44 // ~9 KB ahead, tuned for Xeon 8559C (prefetch into L2)
|
| 363 |
+
+#endif
|
| 364 |
+
+ static int q6pf = -1;
|
| 365 |
+
+ if (q6pf < 0) { const char * e = getenv("GGML_Q6_PF"); q6pf = e ? atoi(e) : Q6_PF_DIST; }
|
| 366 |
+
+ {
|
| 367 |
+
+ const char * pf = (const char *)(x + i + q6pf);
|
| 368 |
+
+ _mm_prefetch(pf, _MM_HINT_T1);
|
| 369 |
+
+ _mm_prefetch(pf + 64, _MM_HINT_T1);
|
| 370 |
+
+ _mm_prefetch(pf + 128, _MM_HINT_T1);
|
| 371 |
+
+ _mm_prefetch(pf + 192, _MM_HINT_T1);
|
| 372 |
+
+ }
|
| 373 |
+
+
|
| 374 |
+
+ const float d = y[i].d * GGML_CPU_FP16_TO_FP32(x[i].d);
|
| 375 |
+
+
|
| 376 |
+
+ const uint8_t * GGML_RESTRICT ql = x[i].ql;
|
| 377 |
+
+ const uint8_t * GGML_RESTRICT qh = x[i].qh;
|
| 378 |
+
+ const int8_t * GGML_RESTRICT q8 = y[i].qs;
|
| 379 |
+
+
|
| 380 |
+
+ // -32 offset handled with bsums
|
| 381 |
+
+ const __m256i q8sums = _mm256_loadu_si256((const __m256i*)y[i].bsums);
|
| 382 |
+
+ const __m256i scales_16 = _mm256_cvtepi8_epi16(_mm_loadu_si128((const __m128i*)x[i].scales));
|
| 383 |
+
+ const __m256i q8sclsub = _mm256_slli_epi32(_mm256_madd_epi16(q8sums, scales_16), 5);
|
| 384 |
+
+ const __m512i scales512 = _mm512_zextsi256_si512(scales_16);
|
| 385 |
+
+
|
| 386 |
+
+ const __m512i QL0 = _mm512_loadu_si512((const void *)(ql));
|
| 387 |
+
+ const __m512i QL1 = _mm512_loadu_si512((const void *)(ql + 64));
|
| 388 |
+
+ const __m512i H0 = _mm512_broadcast_i64x4(_mm256_loadu_si256((const __m256i*)(qh)));
|
| 389 |
+
+ const __m512i H1 = _mm512_broadcast_i64x4(_mm256_loadu_si256((const __m256i*)(qh + 32)));
|
| 390 |
+
+
|
| 391 |
+
+ const __m512i X0 = _mm512_loadu_si512((const void *)(q8));
|
| 392 |
+
+ const __m512i X1 = _mm512_loadu_si512((const void *)(q8 + 64));
|
| 393 |
+
+ const __m512i X2 = _mm512_loadu_si512((const void *)(q8 + 128));
|
| 394 |
+
+ const __m512i X3 = _mm512_loadu_si512((const void *)(q8 + 192));
|
| 395 |
+
+
|
| 396 |
+
+ // 6-bit values (unsigned 0..63): low nibble / high nibble of ql combined with 2 bits of qh
|
| 397 |
+
+ const __m512i q6_0 = _mm512_or_si512(_mm512_and_si512(QL0, m15),
|
| 398 |
+
+ _mm512_and_si512(_mm512_sllv_epi16(H0, shl_cnt), m30));
|
| 399 |
+
+ const __m512i q6_1 = _mm512_or_si512(_mm512_and_si512(_mm512_srli_epi16(QL0, 4), m15),
|
| 400 |
+
+ _mm512_and_si512(_mm512_srlv_epi16(H0, shr_cnt), m30));
|
| 401 |
+
+ const __m512i q6_2 = _mm512_or_si512(_mm512_and_si512(QL1, m15),
|
| 402 |
+
+ _mm512_and_si512(_mm512_sllv_epi16(H1, shl_cnt), m30));
|
| 403 |
+
+ const __m512i q6_3 = _mm512_or_si512(_mm512_and_si512(_mm512_srli_epi16(QL1, 4), m15),
|
| 404 |
+
+ _mm512_and_si512(_mm512_srlv_epi16(H1, shr_cnt), m30));
|
| 405 |
+
+
|
| 406 |
+
+ __m512i sumi = _mm512_zextsi256_si512(_mm256_sub_epi32(_mm256_setzero_si256(), q8sclsub));
|
| 407 |
+
+ sumi = _mm512_dpwssd_epi32(sumi, _mm512_maddubs_epi16(q6_0, X0), _mm512_permutexvar_epi16(sidx0, scales512));
|
| 408 |
+
+ sumi = _mm512_dpwssd_epi32(sumi, _mm512_maddubs_epi16(q6_1, X1), _mm512_permutexvar_epi16(sidx1, scales512));
|
| 409 |
+
+ sumi = _mm512_dpwssd_epi32(sumi, _mm512_maddubs_epi16(q6_2, X2), _mm512_permutexvar_epi16(sidx2, scales512));
|
| 410 |
+
+ sumi = _mm512_dpwssd_epi32(sumi, _mm512_maddubs_epi16(q6_3, X3), _mm512_permutexvar_epi16(sidx3, scales512));
|
| 411 |
+
+
|
| 412 |
+
+ acc = _mm512_fmadd_ps(_mm512_set1_ps(d), _mm512_cvtepi32_ps(sumi), acc);
|
| 413 |
+
+ }
|
| 414 |
+
+
|
| 415 |
+
+ *s = _mm512_reduce_add_ps(acc);
|
| 416 |
+
+
|
| 417 |
+
+#elif defined __AVX2__
|
| 418 |
+
|
| 419 |
+
const __m256i m3 = _mm256_set1_epi8(3);
|
| 420 |
+
const __m256i m15 = _mm256_set1_epi8(15);
|
| 421 |
+
diff --git a/ggml/src/ggml-cpu/ggml-cpu.c b/ggml/src/ggml-cpu/ggml-cpu.c
|
| 422 |
+
index 53d39d249..02889fd24 100644
|
| 423 |
+
--- a/ggml/src/ggml-cpu/ggml-cpu.c
|
| 424 |
+
+++ b/ggml/src/ggml-cpu/ggml-cpu.c
|
| 425 |
+
@@ -35,6 +35,49 @@
|
| 426 |
+
#include <limits.h>
|
| 427 |
+
#include <stdarg.h>
|
| 428 |
+
#include <signal.h>
|
| 429 |
+
+
|
| 430 |
+
+// ---- lightweight per-op profiling (GGML_PROF=1), diagnostic only ----
|
| 431 |
+
+static int g_prof = -1;
|
| 432 |
+
+struct ggml_prof_entry { const char * op; const char * type; const char * ty0; int64_t ne0, ne1, ne2; int64_t us; int64_t calls; };
|
| 433 |
+
+static struct ggml_prof_entry g_prof_tab[1024];
|
| 434 |
+
+static int g_prof_n = 0;
|
| 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 void ggml_prof_add(const struct ggml_tensor * node, int64_t us) {
|
| 452 |
+
+ g_prof_total += us;
|
| 453 |
+
+ const char * op = ggml_op_name(node->op);
|
| 454 |
+
+ const char * ty = ggml_type_name(node->type);
|
| 455 |
+
+ const char * ty0 = node->src[0] ? ggml_type_name(node->src[0]->type) : "-";
|
| 456 |
+
+ const int64_t ne0 = node->ne[0], ne1 = node->ne[1], ne2 = node->ne[2];
|
| 457 |
+
+ for (int i = 0; i < g_prof_n; ++i) {
|
| 458 |
+
+ if (strcmp(g_prof_tab[i].op, op) == 0 && strcmp(g_prof_tab[i].type, ty) == 0 && strcmp(g_prof_tab[i].ty0, ty0) == 0 &&
|
| 459 |
+
+ g_prof_tab[i].ne0 == ne0 && g_prof_tab[i].ne1 == ne1 && g_prof_tab[i].ne2 == ne2) {
|
| 460 |
+
+ g_prof_tab[i].us += us; g_prof_tab[i].calls++;
|
| 461 |
+
+ return;
|
| 462 |
+
+ }
|
| 463 |
+
+ }
|
| 464 |
+
+ if (g_prof_n < 1024) {
|
| 465 |
+
+ g_prof_tab[g_prof_n].op = op; g_prof_tab[g_prof_n].type = ty; g_prof_tab[g_prof_n].ty0 = ty0;
|
| 466 |
+
+ g_prof_tab[g_prof_n].ne0 = ne0; g_prof_tab[g_prof_n].ne1 = ne1; g_prof_tab[g_prof_n].ne2 = ne2;
|
| 467 |
+
+ g_prof_tab[g_prof_n].us = us; g_prof_tab[g_prof_n].calls = 1;
|
| 468 |
+
+ g_prof_n++;
|
| 469 |
+
+ }
|
| 470 |
+
+}
|
| 471 |
+
+// ----------------------------------------------------------------
|
| 472 |
+
#if defined(__gnu_linux__)
|
| 473 |
+
#include <syscall.h>
|
| 474 |
+
#endif
|
| 475 |
+
@@ -3148,6 +3191,13 @@ static thread_ret_t ggml_graph_compute_thread(void * data) {
|
| 476 |
+
continue;
|
| 477 |
+
}
|
| 478 |
+
|
| 479 |
+
+ if (g_prof < 0) {
|
| 480 |
+
+ const char * e = getenv("GGML_PROF");
|
| 481 |
+
+ g_prof = e && e[0] == '1' ? 1 : 0;
|
| 482 |
+
+ if (g_prof) atexit(ggml_prof_dump);
|
| 483 |
+
+ }
|
| 484 |
+
+ const int64_t prof_t0 = (g_prof && state->ith == 0) ? ggml_time_us() : 0;
|
| 485 |
+
+
|
| 486 |
+
// TODO: move fused-op detection into ggml_graph_plan so fusion decisions are made once at planning time
|
| 487 |
+
// Try fused ops, fall back to normal compute
|
| 488 |
+
const int n_fused = ggml_cpu_try_fuse_ops(cgraph, node_n, ¶ms, cplan);
|
| 489 |
+
@@ -3166,6 +3216,9 @@ static thread_ret_t ggml_graph_compute_thread(void * data) {
|
| 490 |
+
if (node_n + 1 < cgraph->n_nodes) {
|
| 491 |
+
ggml_barrier(state->threadpool);
|
| 492 |
+
}
|
| 493 |
+
+ if (g_prof && state->ith == 0) {
|
| 494 |
+
+ ggml_prof_add(node, ggml_time_us() - prof_t0);
|
| 495 |
+
+ }
|
| 496 |
+
}
|
| 497 |
+
|
| 498 |
+
#ifdef GGML_USE_OPENMP
|
| 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
|
| 502 |
+
+++ b/ggml/src/ggml-cpu/tiled/tiled.cpp
|
| 503 |
+
@@ -716,7 +716,9 @@ static void tiled_store_window(const float * buf, int n_src0, int n_src1, int bu
|
| 504 |
+
// unpack and microtile are reused unchanged from mul_mat.
|
| 505 |
+
|
| 506 |
+
// src0 rows per g group; finer than the TILED_TILE_K kernel tile so all threads stay busy at small ne01
|
| 507 |
+
-#define TILED_MMID_GROUP 64
|
| 508 |
+
+#ifndef TILED_MMID_GROUP
|
| 509 |
+
+#define TILED_MMID_GROUP 32
|
| 510 |
+
+#endif
|
| 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).
|
patches/optional-profiler.patch
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
diff --git a/ggml/src/ggml-cpu/ggml-cpu.c b/ggml/src/ggml-cpu/ggml-cpu.c
|
| 2 |
+
index 53d39d249..02889fd24 100644
|
| 3 |
+
--- a/ggml/src/ggml-cpu/ggml-cpu.c
|
| 4 |
+
+++ b/ggml/src/ggml-cpu/ggml-cpu.c
|
| 5 |
+
@@ -35,6 +35,49 @@
|
| 6 |
+
#include <limits.h>
|
| 7 |
+
#include <stdarg.h>
|
| 8 |
+
#include <signal.h>
|
| 9 |
+
+
|
| 10 |
+
+// ---- lightweight per-op profiling (GGML_PROF=1), diagnostic only ----
|
| 11 |
+
+static int g_prof = -1;
|
| 12 |
+
+struct ggml_prof_entry { const char * op; const char * type; const char * ty0; int64_t ne0, ne1, ne2; int64_t us; int64_t calls; };
|
| 13 |
+
+static struct ggml_prof_entry g_prof_tab[1024];
|
| 14 |
+
+static int g_prof_n = 0;
|
| 15 |
+
+static int64_t g_prof_total = 0;
|
| 16 |
+
+
|
| 17 |
+
+static void ggml_prof_dump(void) {
|
| 18 |
+
+ if (g_prof_n == 0) return;
|
| 19 |
+
+ fprintf(stderr, "\n[GGML_PROF] total_us=%" PRId64 "\n", g_prof_total);
|
| 20 |
+
+ for (int i = 0; i < g_prof_n; ++i) {
|
| 21 |
+
+ fprintf(stderr, "[GGML_PROF] %-20s %-6s<%-6s [%6" PRId64 ",%5" PRId64 ",%4" PRId64 "] %9.2f ms %6.2f%% calls=%" PRId64 " us/call=%.1f\n",
|
| 22 |
+
+ 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,
|
| 23 |
+
+ g_prof_tab[i].us/1000.0,
|
| 24 |
+
+ 100.0*g_prof_tab[i].us/(g_prof_total?g_prof_total:1),
|
| 25 |
+
+ g_prof_tab[i].calls,
|
| 26 |
+
+ (double)g_prof_tab[i].us/(g_prof_tab[i].calls?g_prof_tab[i].calls:1));
|
| 27 |
+
+ }
|
| 28 |
+
+ fflush(stderr);
|
| 29 |
+
+}
|
| 30 |
+
+
|
| 31 |
+
+static void ggml_prof_add(const struct ggml_tensor * node, int64_t us) {
|
| 32 |
+
+ g_prof_total += us;
|
| 33 |
+
+ const char * op = ggml_op_name(node->op);
|
| 34 |
+
+ const char * ty = ggml_type_name(node->type);
|
| 35 |
+
+ const char * ty0 = node->src[0] ? ggml_type_name(node->src[0]->type) : "-";
|
| 36 |
+
+ const int64_t ne0 = node->ne[0], ne1 = node->ne[1], ne2 = node->ne[2];
|
| 37 |
+
+ for (int i = 0; i < g_prof_n; ++i) {
|
| 38 |
+
+ if (strcmp(g_prof_tab[i].op, op) == 0 && strcmp(g_prof_tab[i].type, ty) == 0 && strcmp(g_prof_tab[i].ty0, ty0) == 0 &&
|
| 39 |
+
+ g_prof_tab[i].ne0 == ne0 && g_prof_tab[i].ne1 == ne1 && g_prof_tab[i].ne2 == ne2) {
|
| 40 |
+
+ g_prof_tab[i].us += us; g_prof_tab[i].calls++;
|
| 41 |
+
+ return;
|
| 42 |
+
+ }
|
| 43 |
+
+ }
|
| 44 |
+
+ if (g_prof_n < 1024) {
|
| 45 |
+
+ g_prof_tab[g_prof_n].op = op; g_prof_tab[g_prof_n].type = ty; g_prof_tab[g_prof_n].ty0 = ty0;
|
| 46 |
+
+ g_prof_tab[g_prof_n].ne0 = ne0; g_prof_tab[g_prof_n].ne1 = ne1; g_prof_tab[g_prof_n].ne2 = ne2;
|
| 47 |
+
+ g_prof_tab[g_prof_n].us = us; g_prof_tab[g_prof_n].calls = 1;
|
| 48 |
+
+ g_prof_n++;
|
| 49 |
+
+ }
|
| 50 |
+
+}
|
| 51 |
+
+// ----------------------------------------------------------------
|
| 52 |
+
#if defined(__gnu_linux__)
|
| 53 |
+
#include <syscall.h>
|
| 54 |
+
#endif
|
| 55 |
+
@@ -3148,6 +3191,13 @@ static thread_ret_t ggml_graph_compute_thread(void * data) {
|
| 56 |
+
continue;
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
+ if (g_prof < 0) {
|
| 60 |
+
+ const char * e = getenv("GGML_PROF");
|
| 61 |
+
+ g_prof = e && e[0] == '1' ? 1 : 0;
|
| 62 |
+
+ if (g_prof) atexit(ggml_prof_dump);
|
| 63 |
+
+ }
|
| 64 |
+
+ const int64_t prof_t0 = (g_prof && state->ith == 0) ? ggml_time_us() : 0;
|
| 65 |
+
+
|
| 66 |
+
// TODO: move fused-op detection into ggml_graph_plan so fusion decisions are made once at planning time
|
| 67 |
+
// Try fused ops, fall back to normal compute
|
| 68 |
+
const int n_fused = ggml_cpu_try_fuse_ops(cgraph, node_n, ¶ms, cplan);
|
| 69 |
+
@@ -3166,6 +3216,9 @@ static thread_ret_t ggml_graph_compute_thread(void * data) {
|
| 70 |
+
if (node_n + 1 < cgraph->n_nodes) {
|
| 71 |
+
ggml_barrier(state->threadpool);
|
| 72 |
+
}
|
| 73 |
+
+ if (g_prof && state->ith == 0) {
|
| 74 |
+
+ ggml_prof_add(node, ggml_time_us() - prof_t0);
|
| 75 |
+
+ }
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
#ifdef GGML_USE_OPENMP
|