Skip to content

Commit 234564b

Browse files
Some minor tweaks after a first technical review.
1 parent 44e6991 commit 234564b

3 files changed

Lines changed: 52 additions & 38 deletions

File tree

content/learning-paths/mobile-graphics-and-gaming/performance_onnxruntime_kleidiai_sme2/build_ort.md

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,48 +9,58 @@ layout: learningpathall
99
## Build ONNX Runtime and benchmark application with KleidiAI and SME2 support for Android
1010

1111
To run this on an Android device, you must cross-compile ORT using the Android NDK.
12-
Prerequisites
12+
13+
Prerequisites:
1314
- Android NDK: Version r26b or newer (r27+ recommended for latest SME2 toolchain support).
1415
- CMake & Ninja: Ensure these are in your system PATH.
1516

16-
### Build Command
17-
Run the following from the root of the ONNX Runtime repository:
17+
### Build `onnxruntime`
18+
19+
First, clone the [ONNX Runtime](https://github.com/microsoft/onnxruntime).
20+
21+
Then run the following from the root of the ONNX Runtime repository:
1822
```bash
19-
./build.sh --android --android_sdk_path $ANDROID_NDK_HOME --android_ndk_path $ANDROID_NDK_HOME --android_abi arm64-v8a --android_api 27 --config RelWithDebInfo --build_shared_lib --cmake_extra_defines onnxruntime_USE_KLEIDIAI=ON --cmake_generator Ninja --parallel
23+
./build.sh --android --android_sdk_path $ANDROID_NDK_HOME --android_ndk_path $ANDROID_NDK_HOME --android_abi arm64-v8a --android_api 27 --config RelWithDebInfo --build_shared_lib --cmake_extra_defines onnxruntime_USE_KLEIDIAI=ON --cmake_generator Ninja --parallel
2024
```
2125

22-
Note: The flag onnxruntime_USE_KLEIDIAI=ON triggers the inclusion of Arm KleidiAI kernels into the MLAS library.
26+
Note: The flag `onnxruntime_USE_KLEIDIAI=ON` triggers the inclusion of Arm KleidiAI kernels into the MLAS library.
2327

2428
## Profiling Performance with onnxruntime_perf_test
25-
Once the build is complete, you will find the libonnxruntime.so shared library and onnxruntime_perf_test binary in your build directory. The onnxruntime_perf_test is essential for measuring latency and identifying bottlenecks.
29+
Once the build is complete, you will find the `libonnxruntime.so` shared library and `onnxruntime_perf_test` binary in your build directory.
30+
31+
`onnxruntime_perf_test` is essential for measuring latency and identifying bottlenecks of an ONNX model (named `<your_model>.onnx` hereafter).
32+
2633
### Step 1: Push files to Android Device
2734
```bash
2835
adb push <build_dir>/Android/RelWithDebInfo/onnxruntime_perf_test /data/local/tmp/
2936
adb push <build_dir>/Android/RelWithDebInfo/libonnxruntime.so /data/local/tmp/
30-
adb push your_model.onnx /data/local/tmp/
37+
adb push <your_model>.onnx /data/local/tmp/
3138
```
39+
3240
### Step 2: Run the Performance Test
33-
The perf_test tool allows you to simulate inference and gather statistics. For example,
41+
The `onnxruntime_perf_test` tool allows you to simulate inference and gather statistics. For example,
3442
```bash
3543
# Execute on the device
36-
adb shell "/data/local/tmp/onnxruntime_perf_test -e cpu -m times -r 20 -s -Z -x 1 /data/local/tmp/your_model.onnx"
44+
adb shell "/data/local/tmp/onnxruntime_perf_test -e cpu -m times -r 20 -s -Z -x 1 /data/local/tmp/<your_model>.onnx"
3745
```
46+
3847
The command example set the arguments of the application as,
39-
- -e cpu specifies the provider as cpu provider
40-
- -m times specifies the test mode as “times”
41-
- -r 20 specifies the repeated times as 20
42-
- “-Z” disallows thread from spinning during runs to reduce cpu usage
43-
- “-s” shows statistics result
44-
- -x 1 sets the number of threads used to parallelize the execution within nodes as 1
48+
- `-e cpu` specifies the provider as cpu provider
49+
- `-m times` specifies the test mode as “times”
50+
- `-r 20` specifies the repeated times as 20
51+
- `-Z` disallows thread from spinning during runs to reduce cpu usage
52+
- `-s` shows statistics result
53+
- `-x 1` sets the number of threads used to parallelize the execution within nodes as 1
4554

4655
You can try other arguments setting if you would like to.
4756

4857
### Step 3: Deep Dive into Operator Profiling
49-
To see exactly how many milliseconds are spent on each operator, use the profiling flag -p.
58+
To see exactly how many milliseconds are spent on each operator, use the profiling flag `-p`.
5059
```bash
51-
adb shell "/data/local/tmp/onnxruntime_perf_test -p profile.json -e cpu -m times -r 5 -s -Z -x 1 /data/local/tmp/your_model.onnx"
60+
adb shell "/data/local/tmp/onnxruntime_perf_test -p profile.json -e cpu -m times -r 5 -s -Z -x 1 /data/local/tmp/<your_model>.onnx"
5261
adb pull /data/local/tmp/profile.json
5362
```
54-
The argument “-p” enables performance profiling during the benchmark run. When you provide this flag followed by a filename, ONNX Runtime will generate a JSON file containing a detailed trace of the model execution.
55-
You can view the results by opening [prefetto tool]( https://ui.perfetto.dev/), and loading the generated JSON file. This allows you to see a visual timeline of which operations took the most time.
56-
You also can convert the JSON file to a CSV sheet by creating a python script.
63+
64+
The argument `-p` enables performance profiling during the benchmark run. When you provide this flag followed by a filename, ONNX Runtime will generate a JSON file containing a detailed trace of the model execution.
65+
You can view the results by opening [perfetto tool]( https://ui.perfetto.dev/), and loading the generated JSON file. This allows you to see a visual timeline of which operations took the most time.
66+
You also can convert the JSON file to a CSV sheet by creating a python script.

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ ONNX runtime is built with KleidiAI support:
1111
1. Detection: At runtime, MLAS checks the CPU capabilities for SME2 support.
1212
2. Dispatch: If SME2 is detected, MLAS overrides its default kernels. For example, a Gemm (General Matrix Multiplication) operation that would normally use standard vector instructions (such as NEON) is dispatched to a KleidiAI SME2 micro-kernel.
1313

14-
Currently, KleidiAI in MLAS provides ArmKleidiAI::MlasConv, ArmKleidiAI::MlasGemmBatch and ArmKleidiAI::MlasDynamicQGemmBatch kernels.
14+
Currently, KleidiAI in MLAS provides `ArmKleidiAI::MlasConv`, `ArmKleidiAI::MlasGemmBatch` and `ArmKleidiAI::MlasDynamicQGemmBatch` kernels.
1515

1616
### The ArmKleidiAI::MlasConv kernel
17-
Usually, 2D fp32 convolution operators with batch_size=1 and multiple filters (filter kernel is equal or greater than (3,3)) are dispatched to the ArmKleidiAI::MlasConv kernel.
17+
Usually, 2D fp32 convolution operators with batch_size=1 and multiple filters (filter kernel is equal or greater than (3,3)) are dispatched to the `ArmKleidiAI::MlasConv` kernel.
1818

1919
For example, the figure below shows a (7,7) Conv node.
2020

@@ -46,7 +46,7 @@ onnxruntime::InferenceSession::Run
4646
```
4747

4848
### The ArmKleidiAI::MlasGemmBatch kernel
49-
It performs a batched fp32 matrix multiplication (GEMM or GemV) operation using KleidiAI matmul micro kernels. fp32 Conv operators with (1,1) filter kernels also use this kernel.
49+
It performs a batched fp32 matrix multiplication (GEMM or GemV) operation using KleidiAI matmul micro kernels. fp32 Conv operators with (1,1) filter kernels also uses this kernel.
5050

5151
For example, the figure below shows a (1,1) Conv node.
5252

@@ -101,5 +101,5 @@ onnxruntime::InferenceSession::Run
101101
```
102102

103103
### The ArmKleidiAI::MlasDynamicQGemmBatch kernel
104-
This kernel is for Matmul with float output of dynamic quantized A and symmetric quantized B.
105-
It uses KleidiAI *kai_kernel_matmul_clamp_f32_qai8dxp1vlx4_qsi8cxp4vlx4_1vlx4vl_sme2_mopa* micro kernel.
104+
This kernel is for matrix multiplication with float output of dynamic quantized A and symmetric quantized B.
105+
It uses KleidiAI *kai_kernel_matmul_clamp_f32_qai8dxp1vlx4_qsi8cxp4vlx4_1vlx4vl_sme2_mopa* micro kernel.

content/learning-paths/mobile-graphics-and-gaming/performance_onnxruntime_kleidiai_sme2/profiling_example.md

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,22 @@ weight: 5
66
layout: learningpathall
77
---
88

9-
## Profile an ONNX model – Use Resnet50v2 as an example
9+
## Profile an ONNX model – Using Resnet50v2 as an example
1010
The Resnet50v2 fp32 ONNX model can be downloaded from Hugging Face or Modescope.
1111

12-
The Android device that we used is a VIVO X300 phone with MTK D9500 processor, which has Arm C1-Ultra, C1-Premium and C1-Pro CPU cores with SME2 support on it. We chose a C1-Pro CPU core running at 2.0GHz to run the onnxruntime_perf_test benchmark application. You can use any other Android device with SME2 support.
12+
The Android device that we used is a VIVO X300 phone with MTK D9500 processor, which has Arm C1-Ultra, C1-Premium and C1-Pro CPU cores with SME2 support on it. We chose a C1-Pro CPU core running at 2.0GHz to run the `onnxruntime_perf_test` benchmark application. You can use any other Android device with SME2 support.
1313

14-
To compare the performance of running Resnet50v2 on ORT with SME2 and without SME2 support, we built two versions of ORT, one with SME2 support (set *onnxruntime_USE_KLEIDIAI=ON* when building ORT), the other without SME2 support(*onnxruntime_USE_KLEIDIAI=OFF* when building ORT).
14+
To compare the performance of running Resnet50v2 on ORT with SME2 and without SME2 support, we built two versions of ORT, one with SME2 support (set `onnxruntime_USE_KLEIDIAI=ON` when building ORT), the other without SME2 support(`onnxruntime_USE_KLEIDIAI=OFF` when building ORT).
1515

1616
Run following command on the device,
1717
```bash
18-
taskset 1 ./onnxruntime_perf_test -e cpu -r 5 -m times -s -Z -x 1 ./resnet50v2.onnx -p "resnet50v2.onnx_1xC1-Pro_profile
18+
taskset 1 ./onnxruntime_perf_test -e cpu -r 5 -m times -s -Z -x 1 ./resnet50v2.onnx -p resnet50v2.onnx_1xC1-Pro_profile
1919
```
2020

21-
The *taskset 1* in the command sets the CPU affinity of *onnxruntime_perf_test* benchmark to CPU core 0, which is a C1-Pro CPU core.
22-
*-x 1* in the command sets the number of threads used to parallelize the execution within nodes as 1 (single thread).
21+
The `taskset 1` in the command sets the CPU affinity of `onnxruntime_perf_test` benchmark to CPU core 0, which is a C1-Pro CPU core.
22+
`-x 1` in the command sets the number of threads used to parallelize the execution within nodes as 1 (single thread).
2323

24-
Here is output from running onnxruntime_perf_test with ORT with SME2 support as below.
24+
Here is output from running `onnxruntime_perf_test` with ORT with SME2 support as below.
2525
```text
2626
Setting intra_op_num_threads to 1
2727
Disabling intra-op thread spinning between runs
@@ -46,7 +46,7 @@ P99 Latency: 0.101519 s
4646
P999 Latency: 0.101519 s
4747
```
4848

49-
Here is output from running onnxruntime_perf_test with ORT without SME2 support as below.
49+
Here is output from running `onnxruntime_perf_test` with ORT without SME2 support as below.
5050
```text
5151
Setting intra_op_num_threads to 1
5252
Disabling intra-op thread spinning between runs
@@ -70,12 +70,14 @@ P95 Latency: 0.34682 s
7070
P99 Latency: 0.34682 s
7171
P999 Latency: 0.34682 s
7272
```
73-
### Performance
73+
## Performance analysis
7474

75-
We can use [prefetto tool](https://ui.perfetto.dev/), to view the two JSON profile files.
75+
### Using [perfetto tool](https://ui.perfetto.dev/)
76+
77+
We can use [perfetto tool](https://ui.perfetto.dev/) to view the two JSON profile files.
7678

7779
The figure below is a screenshot of the view of the Non-KleidiAI version of JSON profile file.
78-
The selected part(one model_run/SequentialExecutor) in the figure includes information of one inference execution.
80+
The selected part(one `model_run/SequentialExecutor`) in the figure includes information of one inference execution.
7981

8082
![Figure showing profile file of Non-KleidiAI version alt-text#center](images/resnet50v2_no_sme_prefetto.png "prefetto view of Non-KleidiAI version of ORT")
8183

@@ -88,6 +90,8 @@ We also convert the two JSON profile files to CSV sheets, then we combine the in
8890

8991
It shows that ORT with KleidiAI (with SME2) kernels uplifts the performance significantly, especially for convolution operators.
9092

93+
### Using Arm Streamline
94+
9195
If we use Arm Streamline tools and PMU counters for further investigation, in the timeline view of Streamline, we can see SME2 floating point Outer Product and Accumulate (MOPA) instruction is used intensively during the inference.
9296

9397
![Figure showing SME2 instructions and cycles alt-text#center](images/resnet50v2_sme_onnx_streamline_1xgelas_annotation.png "SME2 instructions and cycles shown in Streamline")
@@ -96,7 +100,7 @@ Then we combine the function call view of ORT without KleidiAI and with KleidiAI
96100

97101
![Figure showing function call percentage of both versions of ORT alt-text#center](images/function_call_compare.png "Function call percentage of both versions of ORT in Streamline ")
98102

99-
It shows that KleidiAI kernels provide a significant performance uplift for convolution operators compared to the default MLSA kernels (*MlasSgemmKernelAdd* and *MlasSgemmKernelZero*).
103+
It shows that KleidiAI kernels provide a significant performance uplift for convolution operators compared to the default MLSA kernels (`MlasSgemmKernelAdd` and `MlasSgemmKernelZero`).
100104

101105
## Summary
102-
By integrating KleidiAI (SME2) into ONNX Runtime, you unlock the massive parallel processing power of Arm SME2. This turns the Arm CPU from a "fallback" into a high-performance AI engine capable of running LLMs and complex vision models locally on devices.
106+
By enabling KleidiAI (SME2) into ONNX Runtime, you unlock the massive parallel processing power of Arm SME2. This turns the Arm CPU from a "fallback" into a high-performance AI engine capable of running LLMs and complex vision models locally on devices.

0 commit comments

Comments
 (0)