From f4750e8e51538662917dc122d9bb8f6227b59a7c Mon Sep 17 00:00:00 2001 From: Annie Tallund Date: Wed, 27 May 2026 07:46:44 -0700 Subject: [PATCH 1/2] Add final Gemma4 TODOs for hand-over --- .../gemma4-kleidiai-sme2/_index.md | 21 ++--- .../gemma4-kleidiai-sme2/download_model.md | 29 ++++--- .../gemma4-kleidiai-sme2/introduction.md | 6 +- .../gemma4-kleidiai-sme2/run_llm.md | 79 ++++++++++++++++--- .../gemma4-kleidiai-sme2/setup_workspace.md | 4 + 5 files changed, 98 insertions(+), 41 deletions(-) diff --git a/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/_index.md b/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/_index.md index 6969febd5c..908ba73110 100644 --- a/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/_index.md +++ b/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/_index.md @@ -1,5 +1,5 @@ --- -title: Benchmark Gemma LiteRT-LM prefill performance with KleidiAI and SME2 on macOS +title: Benchmark Gemma 4 LiteRT-LM prefill performance with KleidiAI and SME2 on macOS minutes_to_complete: 45 @@ -7,17 +7,18 @@ draft: true cascade: draft: true -who_is_this_for: This is an advanced topic for software developers and performance engineers who want a reproducible Gemma prefill benchmark workflow using LiteRT-LM, KleidiAI, and XNNPACK on macOS. +who_is_this_for: This is an advanced topic for software developers and performance engineers who want a reproducible Gemma 4 prefill benchmark workflow using LiteRT-LM, KleidiAI, and XNNPACK on macOS. learning_objectives: - Create a pinned workspace with LiteRT-LM, KleidiAI, and XNNPACK - Install Bazelisk and required macOS prerequisites for LiteRT-LM builds - - Prepare a LiteRT-LM compatible `.litertlm` Gemma model from Hugging Face - - Run LiteRT-LM benchmark commands and measure prefill throughput on a reproducible setup + - Prepare a LiteRT-LM-compatible `.litertlm` Gemma 4 model from Hugging Face + - Run LiteRT-LM benchmark commands and compare prefill throughput with SME2 enabled and disabled prerequisites: - A SME2 device (macOS M4 on Apple Silicon) - Git, Homebrew, and Xcode Command Line Tools + - At least 25 GB of free disk space for model files and local builds author: Annie Tallund @@ -63,16 +64,8 @@ further_reading: link: https://github.com/google/xnnpack type: website - resource: - title: google/gemma-3n-E4B-it-litert-lm on Hugging Face - link: https://huggingface.co/google/gemma-3n-E4B-it-litert-lm - type: website - - resource: - title: google/gemma-3-4b-it on Hugging Face - link: https://huggingface.co/google/gemma-3-4b-it - type: website - - resource: - title: litert-community/Gemma3-4B-IT on Hugging Face - link: https://huggingface.co/litert-community/Gemma3-4B-IT + title: litert-community/gemma-4-E4B-it-litert-lm on Hugging Face + link: https://huggingface.co/litert-community/gemma-4-E4B-it-litert-lm type: website diff --git a/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/download_model.md b/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/download_model.md index dfb041af0b..b728662e06 100644 --- a/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/download_model.md +++ b/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/download_model.md @@ -8,7 +8,7 @@ layout: learningpathall ## Overview -In this section, you install the macOS dependencies required to build LiteRT-LM and prepare a Gemma model in LiteRT-LM `.litertlm` format. +In this section, you install the macOS dependencies required to build LiteRT-LM and prepare a Gemma 4 model in LiteRT-LM `.litertlm` format. ## Install prerequisites on macOS @@ -48,44 +48,43 @@ mkdir -p $HOME/gemma4-prefill-bench/LiteRT-LM/models The benchmark commands in this Learning Path assume your model directory is under `LiteRT-LM/models/`. {{% /notice %}} -## Prepare a LiteRT-LM-compatible model +## Prepare a LiteRT-LM-compatible Gemma 4 model LiteRT-LM benchmark commands in this Learning Path use `litert_lm_advanced_main`, which expects a LiteRT-LM model artifact (`.litertlm`) for `--model_path`. -The `google/gemma-3-4b-it` repository on Hugging Face follows the Transformers layout (multiple `safetensors` files), so it is not directly consumable by `litert_lm_advanced_main`. +The base Gemma model repositories on Hugging Face follow the Transformers layout, so they are not directly consumable by `litert_lm_advanced_main`. Use a prebuilt LiteRT-LM model artifact instead: ```bash cd $HOME/gemma4-prefill-bench/LiteRT-LM/models -hf auth login -hf download google/gemma-3n-E4B-it-litert-lm \ - --include "gemma-3n-E4B-it-int4.litertlm" \ - --local-dir ./gemma-3n-E4B-it-litert-lm +hf download litert-community/gemma-4-E4B-it-litert-lm \ + gemma-4-E4B-it.litertlm \ + --local-dir ./gemma-4-E4B-it-litert-lm -cp ./gemma-3n-E4B-it-litert-lm/gemma-3n-E4B-it-int4.litertlm \ - ./gemma-3n-E4B-it-int4.litertlm +cp ./gemma-4-E4B-it-litert-lm/gemma-4-E4B-it.litertlm \ + ./gemma-4-E4B-it.litertlm -ls -lh ./gemma-3n-E4B-it-int4.litertlm +ls -lh ./gemma-4-E4B-it.litertlm ``` {{% notice Note %}} -The model repository is gated. Make sure your Hugging Face account has accepted the model terms before downloading. +If the download is denied, run `hf auth login`, accept the model terms in Hugging Face, and repeat the download command. {{% /notice %}} Expected layout: ```text LiteRT-LM/models/ -├── gemma-3n-E4B-it-int4.litertlm -└── gemma-3n-E4B-it-litert-lm/ - └── gemma-3n-E4B-it-int4.litertlm +├── gemma-4-E4B-it.litertlm +└── gemma-4-E4B-it-litert-lm/ + └── gemma-4-E4B-it.litertlm ``` ## What you've accomplished and what's next In this section: - You installed macOS prerequisites and pinned Bazel for LiteRT-LM -- You created the local model directory and prepared a LiteRT-LM-compatible `.litertlm` Gemma model +- You created the local model directory and prepared a LiteRT-LM-compatible `.litertlm` Gemma 4 model In the next section, you will build and run the benchmark workflow. diff --git a/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/introduction.md b/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/introduction.md index b8617cd494..ef8d26cf41 100644 --- a/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/introduction.md +++ b/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/introduction.md @@ -8,7 +8,7 @@ layout: learningpathall ## Why this benchmark matters -This Learning Path gives you a reproducible process to evaluate Gemma prefill performance improvements when using SME2-optimized paths across LiteRT-LM, KleidiAI, and XNNPACK. +This Learning Path gives you a reproducible process to evaluate Gemma 4 prefill performance improvements when using SME2-optimized paths across LiteRT-LM, KleidiAI, and XNNPACK. The flow in this guide is based on a pinned set of repository commits and a local benchmark command (`litert_lm_advanced_main --benchmark`) so your numbers are comparable across runs. @@ -18,8 +18,8 @@ You will complete the workflow in this order: 1. Create a local workspace and clone LiteRT-LM, KleidiAI, and XNNPACK at tested commits. 2. Install macOS prerequisites and Bazelisk, then pin Bazel to version `7.6.1`. -3. Prepare a LiteRT-LM-compatible `.litertlm` model in `LiteRT-LM/models`. -4. Build LiteRT-LM and run benchmark and sample prompts. +3. Prepare a LiteRT-LM-compatible Gemma 4 `.litertlm` model in `LiteRT-LM/models`. +4. Build LiteRT-LM with SME2 enabled and disabled, then compare benchmark results. In the next section, you will set up the workspace with pinned repository commits. diff --git a/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/run_llm.md b/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/run_llm.md index 71eee0f472..ec405da5e7 100644 --- a/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/run_llm.md +++ b/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/run_llm.md @@ -9,30 +9,71 @@ layout: learningpathall ## Build LiteRT-LM with local XNNPACK and KleidiAI -Build from the LiteRT-LM repository: +Build the SME2-enabled benchmark binary from the LiteRT-LM repository: ```bash cd $HOME/gemma4-prefill-bench/LiteRT-LM bazel build \ --config=macos_arm64 \ + --define=xnn_enable_arm_sme=true \ + --define=xnn_enable_arm_sme2=true \ + --define=xnn_enable_kleidiai=true \ --macos_sdk_version="$(xcrun --sdk macosx --show-sdk-version)" \ --override_repository=XNNPACK=../xnnpack \ --override_repository=KleidiAI=../kleidiai \ //runtime/engine:litert_lm_advanced_main +cp bazel-bin/runtime/engine/litert_lm_advanced_main \ + ./litert_lm_advanced_main_sme2_on ``` -## Run benchmark +Build a second binary with KleidiAI SME and SME2 paths disabled so you can compare the same workload against the XNNPACK fallback on the same machine: ```bash -bazel-bin/runtime/engine/litert_lm_advanced_main \ +bazel build \ + --config=macos_arm64 \ + --define=xnn_enable_arm_sme=false \ + --define=xnn_enable_arm_sme2=false \ + --define=xnn_enable_kleidiai=false \ + --macos_sdk_version="$(xcrun --sdk macosx --show-sdk-version)" \ + --override_repository=XNNPACK=../xnnpack \ + --override_repository=KleidiAI=../kleidiai \ + //runtime/engine:litert_lm_advanced_main + +cp bazel-bin/runtime/engine/litert_lm_advanced_main \ + ./litert_lm_advanced_main_sme2_off +``` + +{{% notice Note %}} +TODO before publication: rerun both binaries on the final pinned upstream XNNPACK and KleidiAI commits, then replace the sample benchmark output with measured Gemma 4 numbers from the same SME2-capable macOS system. +{{% /notice %}} + +## Run benchmarks with and without SME2 + +Run the SME2-enabled benchmark: + +```bash +./litert_lm_advanced_main_sme2_on \ --backend=cpu \ - --model_path=models/gemma-3n-E4B-it-int4.litertlm \ + --model_path=models/gemma-4-E4B-it.litertlm \ --benchmark \ --benchmark_prefill_tokens=512 \ --benchmark_decode_tokens=128 \ --num_cpu_threads=4 \ - --disable_cache=false + --disable_cache=false | tee benchmark-sme2-on.txt +``` + +Run the SME2-disabled benchmark: + +```bash +./litert_lm_advanced_main_sme2_off \ + --backend=cpu \ + --model_path=models/gemma-4-E4B-it.litertlm \ + --benchmark \ + --benchmark_prefill_tokens=512 \ + --benchmark_decode_tokens=128 \ + --num_cpu_threads=4 \ + --disable_cache=false | tee benchmark-sme2-off.txt ``` Example output pattern: @@ -51,16 +92,36 @@ Example output pattern: -------------------------------------------------- ``` +## Verify the SME2 performance uplift + +Compare the prefill throughput from both runs: + +```bash +SME2_ON=$(awk '/Prefill Speed/ {print $3; exit}' benchmark-sme2-on.txt) +SME2_OFF=$(awk '/Prefill Speed/ {print $3; exit}' benchmark-sme2-off.txt) + +SME2_ON="$SME2_ON" SME2_OFF="$SME2_OFF" \ +python3 -c 'import os; on=float(os.environ["SME2_ON"]); off=float(os.environ["SME2_OFF"]); print(f"SME2 prefill uplift: {on/off:.2f}x ({off:.2f} -> {on:.2f} tokens/sec)")' +``` + +For a reliable comparison: + +- Use the same model, token counts, thread count, power state, and terminal session for both runs. +- Run each binary at least three times and compare the median `Prefill Speed`. +- Treat decode throughput separately. This Learning Path focuses on prefill because the SME2-optimized matrix multiplication path has the clearest effect during the prompt-processing phase. + +## Run sample prompts + Run quick output sanity checks: ```bash -bazel-bin/runtime/engine/litert_lm_advanced_main \ +./litert_lm_advanced_main_sme2_on \ --backend=cpu \ - --model_path=models/gemma-3n-E4B-it-int4.litertlm \ + --model_path=models/gemma-4-E4B-it.litertlm \ --input_prompt="What is the capital of France?" -bazel-bin/runtime/engine/litert_lm_advanced_main \ +./litert_lm_advanced_main_sme2_on \ --backend=cpu \ - --model_path=models/gemma-3n-E4B-it-int4.litertlm \ + --model_path=models/gemma-4-E4B-it.litertlm \ --input_prompt="What is the most difficult winter Olympic sport?" ``` diff --git a/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/setup_workspace.md b/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/setup_workspace.md index 8221122ea8..29e1e64eca 100644 --- a/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/setup_workspace.md +++ b/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/setup_workspace.md @@ -10,6 +10,10 @@ layout: learningpathall In this section, you prepare a local workspace and clone the exact LiteRT-LM, KleidiAI, and XNNPACK commits used for this benchmark flow. +{{% notice Note %}} +TODO before publication: replace the pinned KleidiAI and XNNPACK commits below with the final known-good upstream commits after the LiteRT-LM dependency update lands. If LiteRT-LM consumes those upstream revisions directly, remove the local `--override_repository` flags in the build commands and simplify this section to clone only LiteRT-LM. +{{% /notice %}} + Create a working directory and move into it: ```bash From 699faa85be3e5e7c213b80e1e9ffe408ebf5c767 Mon Sep 17 00:00:00 2001 From: Annie Tallund Date: Wed, 26 Aug 2026 15:56:48 -0700 Subject: [PATCH 2/2] Update Gemma4 LP for added kernel support --- .../gemma4-kleidiai-sme2/_index.md | 17 +- .../gemma4-kleidiai-sme2/download_model.md | 73 ++++---- .../gemma4-kleidiai-sme2/introduction.md | 46 +++-- .../gemma4-kleidiai-sme2/run_llm.md | 166 +++++++++--------- .../gemma4-kleidiai-sme2/setup_workspace.md | 69 ++++++-- 5 files changed, 202 insertions(+), 169 deletions(-) diff --git a/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/_index.md b/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/_index.md index aabff9ae1b..baaae9aba2 100755 --- a/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/_index.md +++ b/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/_index.md @@ -10,16 +10,15 @@ cascade: who_is_this_for: This is an advanced topic for software developers and performance engineers who want a reproducible Gemma 4 prefill benchmark workflow using LiteRT-LM, KleidiAI, and XNNPACK on macOS. learning_objectives: - - Create a pinned workspace with LiteRT-LM, KleidiAI, and XNNPACK - - Install Bazelisk and required macOS prerequisites for LiteRT-LM builds - - Prepare a LiteRT-LM-compatible `.litertlm` Gemma 4 model from Hugging Face - - Run LiteRT-LM benchmark commands and compare prefill throughput with SME2 enabled and disabled + - Create a workspace with pinned LiteRT-LM and KleidiAI versions + - Create upstream-optimized and historical-baseline XNNPACK worktrees + - Download a LiteRT-LM-compatible Gemma 4 model from Hugging Face + - Compare baseline and upstream SME2 benchmark results with a cache-neutral workflow prerequisites: - - A SME2 device (macOS M4 on Apple Silicon) + - An SME2 device (this tutorial uses macOS on Apple M4) - Git, Homebrew, and Xcode Command Line Tools - At least 25 GB of free disk space for model files and local builds - author: Annie Tallund generate_summary_faq: true @@ -63,11 +62,11 @@ further_reading: type: website - resource: title: XNNPACK repository - link: https://github.com/google/xnnpack + link: https://github.com/google/XNNPACK type: website - resource: - title: litert-community/gemma-4-E4B-it-litert-lm on Hugging Face - link: https://huggingface.co/litert-community/gemma-4-E4B-it-litert-lm + title: Gemma 4 E2B for LiteRT-LM on Hugging Face + link: https://huggingface.co/litert-community/gemma-4-E2B-it-litert-lm type: website ### FIXED, DO NOT MODIFY diff --git a/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/download_model.md b/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/download_model.md index b728662e06..c42bde00f4 100644 --- a/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/download_model.md +++ b/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/download_model.md @@ -1,18 +1,14 @@ --- -title: Install prerequisites and download the model +title: Install prerequisites and download Gemma 4 weight: 4 ### FIXED, DO NOT MODIFY layout: learningpathall --- -## Overview - -In this section, you install the macOS dependencies required to build LiteRT-LM and prepare a Gemma 4 model in LiteRT-LM `.litertlm` format. - ## Install prerequisites on macOS -Install Xcode Command Line Tools (if needed): +Install Xcode Command Line Tools if they are not already available: ```bash xcode-select --install @@ -27,64 +23,55 @@ brew install bazelisk Install the Hugging Face Hub CLI: ```bash -python3 -m pip install -U "huggingface_hub[cli]" +python3 -m pip install -U huggingface_hub ``` -Pin Bazel version `7.6.1` from the LiteRT-LM root: +Confirm that LiteRT-LM pins Bazel `7.6.1`: ```bash cd $HOME/gemma4-prefill-bench/LiteRT-LM -echo "7.6.1" > .bazelversion +cat .bazelversion bazelisk version ``` -## Create model directory +## Download Gemma 4 from Hugging Face + +Create a shared model directory in the workspace: ```bash -mkdir -p $HOME/gemma4-prefill-bench/LiteRT-LM/models +mkdir -p $HOME/gemma4-prefill-bench/models +cd $HOME/gemma4-prefill-bench ``` -{{% notice Note %}} -The benchmark commands in this Learning Path assume your model directory is under `LiteRT-LM/models/`. -{{% /notice %}} - -## Prepare a LiteRT-LM-compatible Gemma 4 model +Download the CPU-compatible Gemma 4 E2B LiteRT-LM artifact: -LiteRT-LM benchmark commands in this Learning Path use `litert_lm_advanced_main`, which expects a LiteRT-LM model artifact (`.litertlm`) for `--model_path`. +```bash +hf download litert-community/gemma-4-E2B-it-litert-lm \ + gemma-4-E2B-it.litertlm \ + --local-dir models/gemma-4-E2B-it-litert-lm +``` -The base Gemma model repositories on Hugging Face follow the Transformers layout, so they are not directly consumable by `litert_lm_advanced_main`. +The model repository is public. If Hugging Face asks for credentials, run +`hf auth login` and repeat the download. -Use a prebuilt LiteRT-LM model artifact instead: +Verify the downloaded file: ```bash -cd $HOME/gemma4-prefill-bench/LiteRT-LM/models -hf download litert-community/gemma-4-E4B-it-litert-lm \ - gemma-4-E4B-it.litertlm \ - --local-dir ./gemma-4-E4B-it-litert-lm +shasum -a 256 \ + models/gemma-4-E2B-it-litert-lm/gemma-4-E2B-it.litertlm +ls -lh models/gemma-4-E2B-it-litert-lm/gemma-4-E2B-it.litertlm +``` -cp ./gemma-4-E4B-it-litert-lm/gemma-4-E4B-it.litertlm \ - ./gemma-4-E4B-it.litertlm +The expected SHA-256 checksum is: -ls -lh ./gemma-4-E4B-it.litertlm +```output +181938105e0eefd105961417e8da75903eacda102c4fce9ce90f50b97139a63c models/gemma-4-E2B-it-litert-lm/gemma-4-E2B-it.litertlm ``` {{% notice Note %}} -If the download is denied, run `hf auth login`, accept the model terms in Hugging Face, and repeat the download command. +The file is about 2.6 GB. LiteRT-LM requires the `.litertlm` artifact; a +Transformers repository containing only `safetensors` files is not a direct +replacement. {{% /notice %}} -Expected layout: - -```text -LiteRT-LM/models/ -├── gemma-4-E4B-it.litertlm -└── gemma-4-E4B-it-litert-lm/ - └── gemma-4-E4B-it.litertlm -``` - -## What you've accomplished and what's next - -In this section: -- You installed macOS prerequisites and pinned Bazel for LiteRT-LM -- You created the local model directory and prepared a LiteRT-LM-compatible `.litertlm` Gemma 4 model - -In the next section, you will build and run the benchmark workflow. +In the next section, you will build each XNNPACK variant and run the benchmark. diff --git a/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/introduction.md b/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/introduction.md index ef8d26cf41..1450ab77e8 100644 --- a/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/introduction.md +++ b/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/introduction.md @@ -8,36 +8,48 @@ layout: learningpathall ## Why this benchmark matters -This Learning Path gives you a reproducible process to evaluate Gemma 4 prefill performance improvements when using SME2-optimized paths across LiteRT-LM, KleidiAI, and XNNPACK. +This Learning Path gives you a reproducible process to evaluate Gemma 4 CPU +performance with the upstream XNNPACK SME2 Int4 and Int2 paths used through +LiteRT-LM and KleidiAI. -The flow in this guide is based on a pinned set of repository commits and a local benchmark command (`litert_lm_advanced_main --benchmark`) so your numbers are comparable across runs. +The workflow records the repository revisions and uses the +`litert_lm_advanced_main --benchmark` command so that you can compare results +across XNNPACK variants. ## What you will do You will complete the workflow in this order: -1. Create a local workspace and clone LiteRT-LM, KleidiAI, and XNNPACK at tested commits. -2. Install macOS prerequisites and Bazelisk, then pin Bazel to version `7.6.1`. -3. Prepare a LiteRT-LM-compatible Gemma 4 `.litertlm` model in `LiteRT-LM/models`. -4. Build LiteRT-LM with SME2 enabled and disabled, then compare benchmark results. - -In the next section, you will set up the workspace with pinned repository commits. +1. Create a workspace and clone LiteRT-LM `v0.16.1`, KleidiAI `v1.30.0`, and + upstream XNNPACK with the SME2 Int4 and Int2 support. +2. Create a historical XNNPACK baseline worktree from before the SME2 support. +3. Download the Gemma 4 E2B `.litertlm` model from Hugging Face. +4. Build and benchmark the baseline and upstream-optimized variants with + identical settings. +5. Compare steady-state prefill and decode throughput. ## Find out if your device supports SME2 -Confirm your machine exposes SME/SME2 to user space: +Confirm the architecture and macOS SME feature flags: ```bash uname -m -sysctl -a | grep -Ei 'sme2|sme' +sysctl hw.optional.arm.FEAT_SME +sysctl hw.optional.arm.FEAT_SME2 +``` + +The expected output on a supported Apple M4 system is: + +```output +arm64 +hw.optional.arm.FEAT_SME: 1 +hw.optional.arm.FEAT_SME2: 1 ``` -Expected result: -- `uname -m` should report `arm64` -- `sysctl` output should include an SME/SME2 capability entry +If either feature reports `0`, XNNPACK cannot dispatch the SME2 kernels and the +performance comparison is not valid. -If you do not see SME/SME2 in the `sysctl` output, this benchmark can still run, but XNNPACK/KleidiAI will dispatch non-SME2 kernels and your prefill throughput will likely be lower. +For a deeper validation, see [Test your SME2 development +environment](./learning-paths/cross-platform/multiplying-matrices-with-sme2/2-check-your-environment). -{{% notice Note %}} -For a deeper validation (compiler + runtime streaming mode checks), see the cross-platform Learning Path section [Test your SME2 development environment](./learning-paths/cross-platform/multiplying-matrices-with-sme2/2-check-your-environment). -{{% /notice %}} +In the next section, you will set up the benchmark workspace. diff --git a/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/run_llm.md b/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/run_llm.md index ec405da5e7..82f2bff626 100644 --- a/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/run_llm.md +++ b/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/run_llm.md @@ -1,127 +1,131 @@ --- -title: Build and run benchmarks +title: Build and compare benchmarks weight: 5 ### FIXED, DO NOT MODIFY layout: learningpathall --- +## Build and benchmark one XNNPACK variant -## Build LiteRT-LM with local XNNPACK and KleidiAI - -Build the SME2-enabled benchmark binary from the LiteRT-LM repository: +Create directories for the shared Bazel output and benchmark results: ```bash -cd $HOME/gemma4-prefill-bench/LiteRT-LM -bazel build \ - --config=macos_arm64 \ - --define=xnn_enable_arm_sme=true \ - --define=xnn_enable_arm_sme2=true \ - --define=xnn_enable_kleidiai=true \ - --macos_sdk_version="$(xcrun --sdk macosx --show-sdk-version)" \ - --override_repository=XNNPACK=../xnnpack \ - --override_repository=KleidiAI=../kleidiai \ - //runtime/engine:litert_lm_advanced_main - -cp bazel-bin/runtime/engine/litert_lm_advanced_main \ - ./litert_lm_advanced_main_sme2_on +cd $HOME/gemma4-prefill-bench +mkdir -p bazel-output-base results ``` -Build a second binary with KleidiAI SME and SME2 paths disabled so you can compare the same workload against the XNNPACK fallback on the same machine: +Define a shell function that builds one XNNPACK tree and immediately runs the +same three-iteration benchmark: ```bash -bazel build \ +set -o pipefail + +run_variant() { + local variant="$1" + local xnnpack_dir="$2" + local root="$HOME/gemma4-prefill-bench" + local output_base="$root/bazel-output-base/ab" + local model="$root/models/gemma-4-E2B-it-litert-lm/gemma-4-E2B-it.litertlm" + local sdk_version + local binary + + sdk_version="$(xcrun --sdk macosx --show-sdk-version)" + + cd "$root/LiteRT-LM" + bazelisk --output_base="$output_base" build \ --config=macos_arm64 \ - --define=xnn_enable_arm_sme=false \ - --define=xnn_enable_arm_sme2=false \ - --define=xnn_enable_kleidiai=false \ - --macos_sdk_version="$(xcrun --sdk macosx --show-sdk-version)" \ - --override_repository=XNNPACK=../xnnpack \ - --override_repository=KleidiAI=../kleidiai \ + --macos_sdk_version="$sdk_version" \ + --override_repository=XNNPACK="$xnnpack_dir" \ + --override_repository=KleidiAI="$root/kleidiai" \ //runtime/engine:litert_lm_advanced_main -cp bazel-bin/runtime/engine/litert_lm_advanced_main \ - ./litert_lm_advanced_main_sme2_off + binary="$(bazelisk --output_base="$output_base" info bazel-bin)/runtime/engine/litert_lm_advanced_main" + + "$binary" \ + --backend=cpu \ + --model_path="$model" \ + --benchmark \ + --benchmark_prefill_tokens=512 \ + --benchmark_decode_tokens=128 \ + --num_cpu_threads=4 \ + --disable_cache=true \ + --async=false \ + --num_iterations=3 \ + --report_peak_memory_footprint \ + --metric_proto_file_path="$root/results/${variant}.pb" \ + 2>&1 | tee "$root/results/${variant}.log" +} ``` -{{% notice Note %}} -TODO before publication: rerun both binaries on the final pinned upstream XNNPACK and KleidiAI commits, then replace the sample benchmark output with measured Gemma 4 numbers from the same SME2-capable macOS system. -{{% /notice %}} - -## Run benchmarks with and without SME2 +The first build compiles the full LiteRT-LM dependency graph. Reusing one +Bazel output base means that changing the XNNPACK override rebuilds only the +affected actions for later variants. -Run the SME2-enabled benchmark: +Run the historical baseline and the upstream-optimized variant: ```bash -./litert_lm_advanced_main_sme2_on \ - --backend=cpu \ - --model_path=models/gemma-4-E4B-it.litertlm \ - --benchmark \ - --benchmark_prefill_tokens=512 \ - --benchmark_decode_tokens=128 \ - --num_cpu_threads=4 \ - --disable_cache=false | tee benchmark-sme2-on.txt +run_variant baseline "$HOME/gemma4-prefill-bench/xnnpack-baseline" +run_variant optimized "$HOME/gemma4-prefill-bench/xnnpack" ``` -Run the SME2-disabled benchmark: +{{% notice Note %}} +Use `--disable_cache=true` for the A/B comparison. The tested Gemma 4 artifact +contains XNNPACK weight-cache fingerprints that are recognized by the upstream +optimized tree but not by the historical baseline. Enabling caches therefore +makes initialization time and memory use non-comparable. +{{% /notice %}} -```bash -./litert_lm_advanced_main_sme2_off \ - --backend=cpu \ - --model_path=models/gemma-4-E4B-it.litertlm \ - --benchmark \ - --benchmark_prefill_tokens=512 \ - --benchmark_decode_tokens=128 \ - --num_cpu_threads=4 \ - --disable_cache=false | tee benchmark-sme2-off.txt -``` +## Read the benchmark output -Example output pattern: +Each iteration prints output similar to: -```text +```output -------------------------------------------------- - Time to first token: 0.51 s + Time to first token: 0.43 s -------------------------------------------------- Prefill Turns (Total 1 turns): - Prefill Turn 1: Processed 512 tokens in 477.85ms duration. - Prefill Speed: 1071.47 tokens/sec. + Prefill Turn 1: Processed 512 tokens in 399.049292ms duration. + Prefill Speed: 1283.05 tokens/sec. -------------------------------------------------- Decode Turns (Total 1 turns): - Decode Turn 1: Processed 128 tokens in 3.917262s duration. - Decode Speed: 32.68 tokens/sec. + Decode Turn 1: Processed 128 tokens in 4.037520542s duration. + Decode Speed: 31.70 tokens/sec. -------------------------------------------------- ``` -## Verify the SME2 performance uplift +Treat iteration 1 as a warm-up and compare the mean of iterations 2 and 3. -Compare the prefill throughput from both runs: +## Tested results on Apple M4 Pro -```bash -SME2_ON=$(awk '/Prefill Speed/ {print $3; exit}' benchmark-sme2-on.txt) -SME2_OFF=$(awk '/Prefill Speed/ {print $3; exit}' benchmark-sme2-off.txt) - -SME2_ON="$SME2_ON" SME2_OFF="$SME2_OFF" \ -python3 -c 'import os; on=float(os.environ["SME2_ON"]); off=float(os.environ["SME2_OFF"]); print(f"SME2 prefill uplift: {on/off:.2f}x ({off:.2f} -> {on:.2f} tokens/sec)")' -``` +The following results were measured on a 12-core Apple M4 Pro with 24 GB of +RAM, macOS SDK 26.5, four CPU threads, and caches disabled. Frequency and +thermal state were not fixed, so use the values as a functional comparison. -For a reliable comparison: +| XNNPACK variant | Prefill tokens/s | Change | Decode tokens/s | Change | +| --- | ---: | ---: | ---: | ---: | +| Historical baseline | 930.57 | - | 54.78 | - | +| Upstream SME2 Int4 and Int2 | 1263.22 | +35.7% | 29.76 | -45.7% | -- Use the same model, token counts, thread count, power state, and terminal session for both runs. -- Run each binary at least three times and compare the median `Prefill Speed`. -- Treat decode throughput separately. This Learning Path focuses on prefill because the SME2-optimized matrix multiplication path has the clearest effect during the prompt-processing phase. +On this system, the upstream SME2 paths provide a clear prefill improvement but +regress decode for the four-thread workload. Results can differ by model +signature, thread count, SoC, operating system, and thermal state. Measure +prefill and decode separately for your target workload. -## Run sample prompts +## Run a prompt sanity check -Run quick output sanity checks: +After building a variant, use its generated binary for a short prompt: ```bash -./litert_lm_advanced_main_sme2_on \ - --backend=cpu \ - --model_path=models/gemma-4-E4B-it.litertlm \ - --input_prompt="What is the capital of France?" +binary="$(bazelisk --output_base="$HOME/gemma4-prefill-bench/bazel-output-base/ab" info bazel-bin)/runtime/engine/litert_lm_advanced_main" -./litert_lm_advanced_main_sme2_on \ +"$binary" \ --backend=cpu \ - --model_path=models/gemma-4-E4B-it.litertlm \ - --input_prompt="What is the most difficult winter Olympic sport?" + --model_path="$HOME/gemma4-prefill-bench/models/gemma-4-E2B-it-litert-lm/gemma-4-E2B-it.litertlm" \ + --input_prompt="What is the capital of France?" \ + --max_output_tokens=16 \ + --num_cpu_threads=4 \ + --async=false ``` + +The tested model answers that the capital of France is Paris. diff --git a/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/setup_workspace.md b/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/setup_workspace.md index 29e1e64eca..82cff9c896 100644 --- a/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/setup_workspace.md +++ b/content/learning-paths/mobile-graphics-and-gaming/gemma4-kleidiai-sme2/setup_workspace.md @@ -1,48 +1,79 @@ --- -title: Set up workspace and pinned repositories +title: Set up the benchmark workspace weight: 3 ### FIXED, DO NOT MODIFY layout: learningpathall --- -## Overview +## Create the workspace -In this section, you prepare a local workspace and clone the exact LiteRT-LM, KleidiAI, and XNNPACK commits used for this benchmark flow. - -{{% notice Note %}} -TODO before publication: replace the pinned KleidiAI and XNNPACK commits below with the final known-good upstream commits after the LiteRT-LM dependency update lands. If LiteRT-LM consumes those upstream revisions directly, remove the local `--override_repository` flags in the build commands and simplify this section to clone only LiteRT-LM. -{{% /notice %}} - -Create a working directory and move into it: +Create a working directory outside the Learning Paths repository: ```bash mkdir -p $HOME/gemma4-prefill-bench cd $HOME/gemma4-prefill-bench ``` -## Clone tested commits +## Clone the tested LiteRT-LM and KleidiAI versions -Clone the repositories and check out pinned commits: +Clone LiteRT-LM and check out the tested `v0.16.1` commit: ```bash git clone https://github.com/google-ai-edge/LiteRT-LM.git LiteRT-LM -git -C LiteRT-LM checkout 41d6b964c21f225af9dad7088231b024c369adc1 +git -C LiteRT-LM checkout 924e79c91542761242244e4f1651851f822e4cbb +``` +Clone KleidiAI and check out `v1.30.0`, which the upstream XNNPACK SME2 paths +require: + +```bash git clone https://github.com/ARM-software/kleidiai.git kleidiai -git -C kleidiai checkout 72a6a50c1dba714ff27a908e8dd54be3628794b0 +git -C kleidiai checkout 74b1a12d3620c89dae4766de640e064952000f4d +``` + +## Create the XNNPACK variants + +Clone upstream XNNPACK. Its default branch contains the merged SME2 Int4 and +Int2 support and is the optimized tree: -git clone https://github.com/google/xnnpack.git xnnpack -git -C xnnpack checkout deb87c027acd2cca4e59fd1f227e523a1640d24c +```bash +git clone https://github.com/google/XNNPACK.git xnnpack +git -C xnnpack log -1 --oneline ``` -Expected layout: +Record the commit printed by the command so you can identify the exact upstream +revision used for your results. + +Create a historical baseline worktree from the common XNNPACK revision before +the SME2 Int4 and Int2 support: + +```bash +git -C xnnpack worktree add --detach ../xnnpack-baseline \ + eb452a766d8f1075b5491f22309e8f09bd31d828 +``` + +Verify the repository revisions: + +```bash +git -C LiteRT-LM rev-parse HEAD +git -C kleidiai rev-parse HEAD +git -C xnnpack rev-parse HEAD +git -C xnnpack-baseline rev-parse HEAD +``` + +The baseline command should print +`eb452a766d8f1075b5491f22309e8f09bd31d828`. + +The workspace layout is now: -```text +```output gemma4-prefill-bench/ ├── kleidiai/ ├── LiteRT-LM/ -└── xnnpack/ +├── xnnpack/ +└── xnnpack-baseline/ ``` -In the next section, you will install prerequisites and download the model. +In the next section, you will install the prerequisites and download the +Gemma 4 model.