llama.cpp
llama.cpp runs local GGUF models. We measure it on the Orange Pi RV2 (X60, IME1) and the Banana Pi SM10 (K3, IME2). Fork: opensolvers/llama.cpp branch x60-ime-rvv. Raw notes: benchmarks/llamacpp.
Prompt and decode are tokens/s. Unless a column says otherwise, that is 128 prompt tokens and 32 generated tokens (llama-bench -p 128 -n 32).
K3 — Banana Pi SM10
Eight A100 cores at 1.8 GHz, use_ime2: 1. Q4_0 is r=3 at fork 72d1824. Q3_K_M and TinyLlama are r=3 at 107ead2f2.
| 1 core | 2 cores | 4 cores | 8 cores | |
|---|---|---|---|---|
| Q4_0 prompt | 76.43 | 149.65 | 291.12 | 525.96 |
| Q4_0 decode | 21.90 | 40.24 | 58.67 | 38.78 |
| Q3_K_M prompt | 69.04 | — | 266.35 | 499.23 |
| Q3_K_M decode | 19.14 | — | 45.56 | 47.95 |
| TinyLlama prompt | 35.73 | — | 138.25 | 254.37 |
| TinyLlama decode | 10.93 | — | 35.13 | 43.39 |
Q4_0 decode peaks at 4 cores. Q3_K_M and TinyLlama peak at 8. The same Q4_0 file on the X100 (RVV, 8 cores) is 193.68 / 41.95, so IME2 prompt is 2.7× that core. On the RV2 the same file at 8 cores is IME 69.03 / 1.47 and RVV 100.60 / 12.18.
The Q3_K_M file is mostly IQ4_NL, not Q3_K. Its 8-core prompt is 5% under Q4_0. TinyLlama is tagged Q2_K; most of its matmuls are Q3_K, and this prompt rate is 1.24× the previous kernel (205.17). Stock RVV on the A100 has no VLEN=1024 Q4_0 kernel and lands at 6.68 / 4.27. Notes: Q4_0, Q3_K_M, TinyLlama.
Ten Q4_0 models
Eight cores on both boards, same bench. RV2 is the X60 (IME1 and RVV). SM10 is the K3 A100 (IME2), one repeat at fork 107ead2f2. × is the SM10 result divided by the faster RV2 result on that row. Prompt is about 5–8×. Decode is about 3–5×.
On the RV2, IME wins prompt from 1.1B up and RVV wins every decode, so the prompt × uses IME except on the 0.5B, and every decode × uses RVV. The RV2 has 7.7 GiB and no swap, so 7B is the practical ceiling there. Qwen2.5 3B on the SM10 repeated G, so that row is a failed run. Qwen2.5 7B is the two-shard file. The same 3B model at Q4_K_M is coherent.
The 0.5B SM10 cells are one repeat. The r=3 mean for that file is prompt 525.96 and decode 38.78 at 8 cores, with decode peaking at 58.67 on 4 cores.
| Model | Prompt RV2 IME | Prompt RV2 RVV | Prompt SM10 | × | Decode RV2 IME | Decode RV2 RVV | Decode SM10 | × |
|---|---|---|---|---|---|---|---|---|
| Qwen2.5 0.5B | 69.03 | 100.60 | 540.21 | 5.4× | 1.47 | 12.18 | 57.78 | 4.7× |
| TinyLlama 1.1B | 37.72 | 34.95 | 279.67 | 7.4× | 1.72 | 9.47 | 35.26 | 3.7× |
| Llama 3.2 1B | 38.87 | 25.27 | 291.49 | 7.5× | 2.00 | 7.74 | 25.86 | 3.3× |
| Qwen2.5 1.5B | 27.14 | 22.77 | 204.11 | 7.5× | 1.19 | 6.10 | 22.83 | 3.7× |
| Gemma 2 2B | 17.56 | 10.04 | 114.81 | 6.5× | 1.01 | 3.15 | 10.53 | 3.3× |
| Qwen2.5 3B (failed) | 14.13 | 7.85 | 103.75 | 7.3× | 0.85 | 3.12 | 12.32 | 3.9× |
| Llama 3.2 3B | 13.99 | 6.95 | 108.70 | 7.8× | 1.05 | 3.09 | 11.72 | 3.8× |
| Phi-3.5 mini | 11.37 | 4.59 | 78.99 | 6.9× | 1.11 | 2.02 | 10.48 | 5.2× |
| Mistral 7B | 5.84 | 2.35 | 45.57 | 7.8× | 0.73 | 1.38 | 5.75 | 4.2× |
| Qwen2.5 7B | 6.06 | 2.52 | 48.81 | 8.1× | 0.73 | 1.38 | 5.70 | 4.1× |
Sources: model_validation.tsv, results_sm10_model_suite.md.
Seventeen Q4_K_M models
Same files. × is the SM10 result divided by the faster RV2 result on that row, as in the table above. RV2 columns are 512 prompt tokens and 64 generated tokens (IME1 m1gemv vs RVV). SM10 columns are 128 and 32 (IME2, one repeat). Prompt × is about 7–18× and decode × is about 3–6×. The prompt factor is larger because the RV2 prompt is the longer one. On the RV2, RVV wins every decode and prompt is close; Q4_K does not engage smt.vmadot there. On the SM10, Q4_K uses the IME2 Q4 kernel and all 17 completions are coherent. StableLM 2 1.6B is the Zephyr GGUF. DeepSeek Coder described RISC-V as an ARM ISA, and the DeepSeek-R1 distill opened with a thinking trace.
| Model | Prompt RV2 IME | Prompt RV2 RVV | Prompt SM10 | × | Decode RV2 IME | Decode RV2 RVV | Decode SM10 | × |
|---|---|---|---|---|---|---|---|---|
| Qwen2.5 0.5B | 23.92 | 20.73 | 433.34 | 18.1× | 1.42 | 9.19 | 51.44 | 5.6× |
| Llama 3.2 1B | 24.13 | 27.49 | 219.68 | 8.0× | 1.90 | 8.19 | 24.49 | 3.0× |
| Gemma 3 1B | 12.75 | 11.36 | 191.69 | 15.0× | 1.04 | 4.40 | 22.63 | 5.1× |
| DeepSeek Coder 1.3B | 16.51 | 16.43 | 172.65 | 10.5× | 1.37 | 6.91 | 25.31 | 3.7× |
| Qwen2.5 1.5B | 18.62 | 18.80 | 147.25 | 7.8× | 1.14 | 6.31 | 20.09 | 3.2× |
| StableLM 2 Zephyr 1.6B | 16.58 | 20.65 | 167.67 | 8.1× | 1.17 | 6.74 | 21.19 | 3.1× |
| Falcon 3 1B | 19.57 | 22.49 | 179.10 | 8.0× | 1.69 | 7.28 | 21.78 | 3.0× |
| SmolLM2 1.7B | 13.62 | 15.46 | 132.45 | 8.6× | 1.35 | 5.94 | 18.90 | 3.2× |
| DeepSeek R1 Qwen 1.5B | 18.54 | 19.10 | 147.74 | 7.7× | 1.14 | 6.38 | 20.06 | 3.1× |
| Granite 3.1 2B | 9.23 | 10.48 | 86.95 | 8.3× | 0.80 | 4.04 | 12.98 | 3.2× |
| Gemma 2 2B | 11.43 | 12.07 | 87.09 | 7.2× | 0.97 | 3.25 | 9.07 | 2.8× |
| Qwen2.5 3B | 8.25 | 8.93 | 73.31 | 8.2× | 0.79 | 3.43 | 10.69 | 3.1× |
| Falcon 3 3B | 10.37 | 10.68 | 82.71 | 7.7× | 1.17 | 3.74 | 9.94 | 2.7× |
| Llama 3.2 3B | 8.59 | 9.14 | 77.84 | 8.5× | 0.96 | 3.30 | 10.37 | 3.1× |
| Phi-3.5 mini | 4.08 | 2.91 | 50.79 | 12.4× | 0.69 | 2.04 | 9.25 | 4.5× |
| Gemma 3 4B | 7.67 | 7.68 | 58.17 | 7.6× | 0.70 | 2.52 | 7.48 | 3.0× |
| Phi-4 mini | 5.33 | 4.14 | 60.76 | 11.4× | 0.76 | 2.17 | 8.39 | 3.9× |
Sources: results_17model_m1gemv_vs_rvv.md, results_sm10_model_suite.md. The BXM-4-64 GPU is still unmeasured.
Build
On an X60, with an assembler that accepts smt.vmadot (toolchain):
git clone -b x60-ime-rvv https://github.com/opensolvers/llama.cpp.git
cd llama.cpp
cmake -B build -DCMAKE_BUILD_TYPE=Release \
-DGGML_CPU_RISCV64_SPACEMIT=ON \
-DGGML_RVV=ON -DGGML_RV_ZVFH=ON -DGGML_RV_ZFH=ON \
-DGGML_RV_ZBA=ON -DGGML_RV_ZICBOP=ON
cmake --build build --parallel "$(nproc)"
Pin IME to cluster 0 (taskset -c 0-3). Startup should report use_ime1: 1. A second build with GGML_CPU_RISCV64_SPACEMIT=OFF is the RVV arm. Branch docs: build-riscv64-spacemit.md. Harnesses: benchmarks/llamacpp.
On the K3, write the shell pid to /proc/set_ai_thread before exec, then taskset -c 8-15. See SM10.
Kernels on the fork
| Change | Result |
|---|---|
| Q8_0 / Q6_K GEMM | Q8_0 prompt 62.7 t/s at 4 cores, vs 25.5 on the stock IME build |
| Scale-build | +4.3% on an isolated Q4_0 GEMM (22.50 → 23.47 GOP/s) |
xsmtvdot asm |
Builds with binutils ≥ 2.46 |
| RVV softmax | 212/212 tests; about 2.1× on a large shape |
| M1 GEMV | Q8_0 decode 0.82 → 5.29 t/s. On RV2 Q4_K_M this build is slower than RVV |
Q8_0 hybrid stores weights twice and uses IME only when the row count is at least 4. Decode goes back to the stock path. SPACEMIT_HYBRID=1.
| Build | Q8_0 prompt | Q8_0 decode |
|---|---|---|
| IME only | 83.7 | 0.83 |
| Hybrid | 90.1 | 6.68 |
| RVV only | 27.0 | 5.11 |
TCM off on the RV2. Staging panels through TCM slows the real model: Q8_0 prompt 70.1 → 50.4, Q4_0 prompt 96.8 → 49.9. Keep SPACEMIT_DISABLE_TCM=1. Details: RV2.