Skip to content

Commit 9f30c3e

Browse files
Update performance_llama_cpp_sme2 content
1 parent 92933cf commit 9f30c3e

4 files changed

Lines changed: 62 additions & 37 deletions

File tree

content/learning-paths/mobile-graphics-and-gaming/performance_llama_cpp_sme2/build_llama_cpp.md

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ weight: 4
66
layout: learningpathall
77
---
88

9+
## Overview
10+
911
In this section, you set up a GCC cross-compile toolchain and build a statically linked `llama-cli` binary with KleidiAI and SME2 enabled.
1012

11-
For convenience, llama.cpp is statically linked. You use the aarch64 GCC cross compile toolchain, *aarch64-none-linux-gnu-*, to build the project. To support SME2, GCC compiler version 14.2 and onwards is required.
13+
For convenience, llama.cpp is statically linked. You use the aarch64 GCC cross compile toolchain, `aarch64-none-linux-gnu-`, to build the project. To support SME2, GCC compiler version 14.2 or later is required.
1214

1315
The build uses the Linux-hosted Arm GNU Toolchain. If you are working on macOS or Windows, run these commands in a Linux environment (for example, a Linux VM, container, or a Linux development machine).
1416

@@ -36,33 +38,33 @@ tar -xf "${TOOLCHAIN_TAR}"
3638
export PATH="$PWD/${TOOLCHAIN_TAR%.tar.xz}/bin:$PATH"
3739
```
3840

39-
Verify the installation was successful by printing the toolchain version:
41+
Confirm the installation succeeded by printing the compiler version:
4042

4143
```bash
4244
aarch64-none-linux-gnu-gcc --version
4345
```
4446

4547
## Clone the llama.cpp repository
4648

47-
The llama.cpp with tag b7610 is used in this tutorial. Newer versions should also work, but they are not tested.
49+
This Learning Path uses llama.cpp tag b7610. Newer versions should also work but are not tested.
4850

49-
Next, download the llama.cpp source code and check out the tag used in this tutorial:
51+
Download the llama.cpp source code and check out that tag:
5052

5153
```bash
5254
cd $HOME
5355
git clone --depth 1 --branch b7610 https://github.com/ggml-org/llama.cpp.git
5456
```
5557

56-
Create a new directory *build* under the llama.cpp root directory and change to the new directory:
58+
Create a new `build` directory under the llama.cpp root directory and change to it:
5759

5860
```bash
5961
cd $HOME/llama.cpp
6062
mkdir build && cd build
6163
```
6264

63-
## Compile the binary
65+
## Compile llama-cli for Android
6466

65-
Next, configure the project using the following command:
67+
Configure the project. The key flags enable KleidiAI support (`-DGGML_CPU_KLEIDIAI=ON`) and SME2 instructions (`-march=...+sme2`), produce a statically linked binary (`-static`) that runs across Android and Linux environments, and include debug symbols (`-g`) for profiling:
6668

6769
```bash
6870
cmake .. \
@@ -91,16 +93,22 @@ Set `CMAKE_C_COMPILER` and `CMAKE_CXX_COMPILER` to your cross compiler path if i
9193

9294
The `-static` and `-g` options are specified to produce a statically linked executable, in order to run on different Arm64 Linux/Android environments and include debug information.
9395

94-
Next, build the project,
96+
Build the project:
9597

9698
```bash
9799
cd $HOME/llama.cpp/build
98100
cmake --build ./ --config Release -j $(nproc)
99101
```
100-
After the building process completes, verify that *llama-cli* exists in the binary directory:
102+
After the build completes, confirm that `llama-cli` exists in the binary directory:
101103

102104
```bash
103105
ls -la $HOME/llama.cpp/build/bin | grep llama-cli
104106
```
105107

106-
Now that you have a `llama-cli` build with KleidiAI enabled, move on to the next section to run the model on your SME2 device and observe the performance impact when you enable the microkernels.
108+
## What you've accomplished and what's next
109+
110+
In this section:
111+
- You installed the Arm GNU Toolchain (GCC 14.2) and configured it for aarch64 cross-compilation
112+
- You built a statically linked `llama-cli` binary with KleidiAI and SME2 enabled, ready to run on your Android target
113+
114+
In the next section, you'll transfer the binary and model to the device and compare inference performance with SME2 on and off.

content/learning-paths/mobile-graphics-and-gaming/performance_llama_cpp_sme2/introduction.md

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,28 @@
11
---
2-
title: Overview
2+
title: Understand how SME2 and KleidiAI accelerate LLM inference in llama.cpp
33
weight: 2
44

55
### FIXED, DO NOT MODIFY
66
layout: learningpathall
77
---
8+
## How SME2 and KleidiAI accelerate LLM inference in llama.cpp
89

9-
## Introduction
10-
In this section, you get a quick mental model of SME2, KleidiAI, and what llama.cpp is doing when it runs LLM inference on an Arm CPU.
11-
Arm’s latest Client CPU processors such as Arm C1 include Scalable Matrix Extension 2 (SME2). SME2 accelerates the matrix-heavy AI operations behind large language models (LLMs), media processing, speech recognition, computer vision, real-time apps and multimodal apps.
10+
In this Learning Path, you'll optimize llama.cpp inference on an Arm CPU by enabling SME2 acceleration through Arm KleidiAI microkernels.
1211

13-
llama.cpp provides extensive support for many LLMs, including Phi, Llama, DeepSeek, Gemma and Qwen. It's designed for efficient CPU-based inference, enabling on-device LLM execution that reduces latency and enhances privacy.
12+
You will measure the performance difference between the default CPU path and the SME2-optimized path using a 3 billion parameter LLM. By the end, you will understand:
1413

15-
By default, llama.cpp integrates with Arm KleidiAI, a suite of optimized microkernels for Arm CPUs. KleidiAI includes SME2-optimized microkernels to deliver additional performance benefits.
14+
- What SME2 changes in the matrix execution path
15+
- How KleidiAI integrates into llama.cpp’s CPU backend
16+
- How to verify that SME2 microkernels are active
17+
- What measurable improvement you should expect
1618

17-
This Learning Path uses the `Llama-3.2-3B-Instruct-Q4_0.gguf` model with 3 billion parameters.
19+
Scalable Matrix Extension 2 (SME2) is an Arm architectural feature designed to accelerate matrix-heavy workloads. Large language model (LLM) inference relies heavily on matrix multiplication, especially in transformer layers. When SME2 is available on the CPU, KleidiAI provides optimized microkernels that replace generic implementations inside llama.cpp.
1820

19-
Move on to the next section to see how KleidiAI microkernels integrate into llama.cpp's CPU backend.
21+
llama.cpp is a CPU-focused LLM inference engine. On Arm systems, it integrates with KleidiAI by default. If SME2 is supported and enabled at runtime, llama.cpp dispatches SME2-optimized matrix kernels for supported operations.
22+
23+
This Learning Path uses the `Llama-3.2-3B-Instruct-Q4_0.gguf` model (3 billion parameters) as a reproducible test case.
24+
25+
In the next section, you'll examine how KleidiAI microkernels integrate into the llama.cpp backend and where SME2 is activated in the execution path.
2026

2127

2228

content/learning-paths/mobile-graphics-and-gaming/performance_llama_cpp_sme2/kleidiai_integration.md

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
11
---
2-
title: Integration of SME2 optimized KleidiAI microkernels in llama.cpp
2+
title: Trace how KleidiAI and SME2 accelerate llama.cpp from model load to token decode
33
weight: 3
44

55
### FIXED, DO NOT MODIFY
66
layout: learningpathall
77
---
88

9-
## Integration of SME2 optimized KleidiAI microkernels in llama.cpp
10-
In this section, you look at how SME2 connects into the Arm software ecosystem by following the path from llama.cpp, through its ggml CPU backend, down to Arm KleidiAI microkernels that take advantage of SME2 when the hardware supports it.
9+
## Overview
10+
11+
In this section, you trace how SME2 acceleration flows through llama.cpp across the full inference lifecycle — from model load to prefill and token decode.
12+
13+
Rather than treating SME2 as a feature flag, you examine where acceleration is selected, how weights and activations are packed, and which microkernels execute at each stage of inference. You follow the path from high-level llama.cpp operations down into the ggml-cpu backend and finally into the KleidiAI microkernels that use SME2, I8MM, or DotProd instructions depending on hardware support.
14+
15+
By the end of this section, you will understand:
16+
- Where KleidiAI integrates into the llama.cpp CPU backend
17+
- Which operators are eligible for SME2 acceleration
18+
- How microkernel selection priority works (SME2 → I8MM → DotProd)
19+
- What changes between model load, prefill, and token decode
20+
21+
This architectural view prepares you to build, profile, and validate SME2 acceleration in the next sections.
1122

1223
### Where does KleidiAI fit in the llama.cpp CPU backend?
1324

@@ -21,7 +32,7 @@ The integration source code is located in the following directory of llama.cpp:
2132
./ggml/src/ggml-cpu/kleidiai
2233
```
2334

24-
### Which matmul operators can use KleidiAI microkernels?
35+
### Which matmul operators can use KleidiAI microkernels?
2536

2637
KleidiAI matmul microkernels can be used for some types of `GGML_OP_MUL_MAT` operators. The table below lists some matmul operators with specific input and output data type that can be accelerated by KleidiAI microkernels.
2738

@@ -39,7 +50,7 @@ In this table, LHS is short for left-hand source (left-hand input matrix) and RH
3950

4051
More operators and data types are being supported by KleidiAI microkernels.
4152

42-
### How does the KleidiAI path work?
53+
### How the KleidiAI microkernel selection and packing path works
4354

4455
The figure below shows how KleidiAI microkernels are used for `matmul` with `GGML_TYPE_Q4_0` or `GGML_TYPE_Q8_0` RHS(weight).
4556

@@ -54,11 +65,11 @@ SME2 -> I8MM -> DotProd
5465
```
5566
Once the matmul microkernel is decided, its corresponding RHS packing and LHS quantizing & packing micro-kernel will be used.
5667

57-
## Call stacks
68+
## Execution call stacks for KleidiAI microkernels
5869

5970
The call stacks below are included as a way to make this integration concrete. Read each stack from top to bottom: the top frames show the high-level llama.cpp operation you triggered (loading the model or decoding tokens), the middle frames show where execution enters the `ggml-cpu` backend, and the bottom frame is the specific KleidiAI microkernel that runs. The first stack shows a one-time weight repack during model load, which happens because the model weights are constant during inference. The later stacks show what happens during inference: activations change from token to token, so the LHS is quantized and packed each time, and then the selected SME2 GEMM or GEMV microkernel executes the matmul.
6071

61-
### During model load
72+
### RHS weight packing during model load
6273

6374
In case of using the Llama-3.2-3B-Instruct-Q4_0.gguf model and SME2 microkernels, RHS packing is done by the *kai_run_rhs_pack_nxk_qsi4c32ps1s0scalef16_qsu4c32s16s0_neon* microkernel when loading the model. It is shown in following function call stack,
6475

@@ -72,7 +83,7 @@ llama_model_load
7283
kai_run_rhs_pack_nxk_qsi4c32ps1s0scalef16_qsu4c32s16s0_neon
7384
```
7485

75-
### During inference
86+
### LHS activation quantization during inference
7687

7788
The F32 activation input matrix (LHS) is dynamically quantized and packed by the *kai_run_lhs_quant_pack_qsi8d32p_f32_neon* microkernel every time, since the activation input keeps changing during the model run. It is done by following function call stack,
7889

@@ -92,7 +103,7 @@ llama_context::decode
92103
```
93104
Once the LHS and RHS is ready, KleidiAI matmul microkernel can be executed.
94105

95-
### During prefill
106+
### SME2 GEMM microkernel execution during prefill
96107

97108
`Llama-3.2-3B-Instruct-Q4_0.gguf` model and 512-bit SME2 streaming vector length are used as an example. At the Prefill stage, the KleidiAI GEMM microkernel optimized with SME2, *kai_matmul_clamp_f32_qsi8d32p1vlx4_qsi4c32p4vlx4_1vlx4vl_sme2_mopa*, is selected by the KleidiAI trait, it produces a dequantized F32 output matrix. It is done right after LHS quantizing and packing by function call stack shown below.
98109
```text
@@ -111,7 +122,7 @@ llama_context::decode
111122
kai_matmul_clamp_f32_qsi8d32p1vlx4_qsi4c32p4vlx4_1vlx4vl_sme2_mopa
112123
```
113124

114-
### During token decode
125+
### SME2 GEMV microkernel execution during token decode
115126

116127
At the LLM decode stage, KleidiAI GEMV micro-kernel optimized with SME2, *kai_run_matmul_clamp_f32_qsi8d32p1x4_qsi4c32p4vlx4_1x4vl_sme2_sdot*, is selected by the KleidiAI trait in llama.cpp, it produces a dequantized F32 output vector. It is done right after LHS quantizing & packing by function call stack shown below,
117128

content/learning-paths/mobile-graphics-and-gaming/performance_llama_cpp_sme2/run_llm.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
---
2-
title: Run the Llama-3.2-3B-Instruct-Q4_0.gguf model with llama-cli
2+
title: Measure SME2 acceleration in llama.cpp on Android
33
weight: 5
44

55
### FIXED, DO NOT MODIFY
66
layout: learningpathall
77
---
88

9-
## Run the Llama-3.2-3B-Instruct-Q4_0.gguf model with llama-cli
9+
## Compare performance with SME2 enabled and disabled
1010

1111
In this section, you run the model on an SME2-capable Android device and compare performance with SME2 enabled and disabled.
1212

@@ -19,8 +19,8 @@ curl -L -o Llama-3.2-3B-Instruct-Q4_0.gguf \
1919
https://huggingface.co/unsloth/Llama-3.2-3B-Instruct-GGUF/resolve/main/Llama-3.2-3B-Instruct-Q4_0.gguf
2020
```
2121

22-
## Transfer the files using ADB
23-
This subsection shows a repeatable way to copy your `llama-cli` binary and GGUF model from your host machine to an Android target device, and then run the same commands from an interactive shell on the device.
22+
### Transfer the files using ADB
23+
This section shows a repeatable way to copy your `llama-cli` binary and GGUF model from your host machine to an Android target device, and then run the same commands from an interactive shell on the device.
2424

2525
Enable **Developer options** and **USB debugging** on the Android device, connect it over USB (or over the network if your setup supports it), and verify that your host can see the device:
2626

@@ -47,7 +47,7 @@ cd /data/local/tmp/llama_sme2
4747
The figure below shows the architecture of the Llama-3.2-3B model:
4848
![Architecture diagram of the Llama-3.2-3B model showing the transformer block structure, including attention heads, feed-forward layers, and the overall token embedding and output projection flow alt-txt#center](images/llama-3.2-3b_architecture.jpg "Architecture of Llama-3.2-3B")
4949

50-
## Inference with SME2 enabled
50+
### Run inference with SME2 enabled
5151

5252
To enable SME2 microkernels, set the `GGML_KLEIDIAI_SME` environment variable before running the application. The flags used here are: `taskset 2` pins the process to CPU core 2 (the Arm C1-Pro core), `-st` enables single-token generation mode to report per-token performance stats, `-C 0x2 -Cb 0x2` sets CPU affinity for operator execution, and `-t 1` limits inference to one thread. If `taskset` is not available on your device, run the command without it.
5353

@@ -67,7 +67,7 @@ With the SME2 kernels enabled, you'll notice the following performance output:
6767

6868
Your results will vary depending on the device and the SME2 streaming vector length available.
6969

70-
## Baseline performance without SME2
70+
### Baseline performance without SME2
7171

7272
For a performance comparison, run the model with SME2 microkernels disabled. In this scenario, I8MM and DotProd microkernels are used instead.
7373

@@ -81,7 +81,7 @@ The output is similar to:
8181
[ Prompt: 7.9 t/s | Generation: 5.9 t/s ]
8282
```
8383

84-
## Optional: Use Streamline to profile
84+
## Profile with Arm Streamline (optional)
8585

8686
You can profile the model execution with the approach introduced in [Profile llama.cpp performance with Arm Streamline and KleidiAI LLM kernels](https://learn.arm.com/learning-paths/servers-and-cloud-computing/llama_cpp_streamline/).
8787

@@ -93,7 +93,7 @@ The Streamline Call Paths view below indicates similar speedup, it also shows th
9393

9494
![Arm Streamline Call Paths view comparing inference with SME2 enabled against DotProd and I8MM fallback paths, showing the KleidiAI microkernel selected in each case alt-txt#center](images/streamline_call_paths_combined.jpg "Combined Streamline Call Paths view with and without SME2")
9595

96-
## Optional: Print the kernel names at runtime
96+
## Print KleidiAI kernel names at runtime (optional)
9797

9898
To investigate which operators in the model graph are delegated to KleidiAI microkernels, you can add some code as below to `./ggml/src/ggml-cpu/kleidiai/kleidiai.cpp` and recompile the binary. When you run the inference, the names of operators that make use of KleidiAI microkernels will be printed. This is only for debugging purposes.
9999

@@ -127,7 +127,7 @@ kai matmul Q4_0 ffn_up-27
127127
kai matmul Q4_0 ffn_out-27
128128
```
129129

130-
## Summary
130+
## What you've accomplished and what's next
131131

132132
You've run a quantized LLM on an SME2-capable Android device and measured the throughput difference with KleidiAI SME2 microkernels enabled and disabled. The results demonstrate meaningful gains at both the Prefill and Decode stages, making on-device LLM inference faster and more power-efficient on Arm hardware.
133133

0 commit comments

Comments
 (0)