Skip to content

Commit 9605b72

Browse files
authored
Merge pull request #3149 from odincodeshen/v9_mnn
LP: Multimodal On-Device Inference on Armv9 with MNN for Audio and Vision
2 parents ee8043c + a7a0b26 commit 9605b72

10 files changed

Lines changed: 817 additions & 0 deletions

File tree

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
---
2+
title: Run multimodal inference with MNN on Armv9
3+
layout: learningpathall
4+
weight: 2
5+
---
6+
7+
## Introduction
8+
9+
This section introduces the software stack used throughout this Learning Path. You will use **[MNN](https://github.com/alibaba/MNN)** to run a prebuilt **Omni multimodal model** on an Armv9 Linux system using only the CPU.
10+
11+
By the end of this section, you will understand why this combination is a practical starting point for reproducible multimodal inference on Armv9, and use retail restocking workflow as an example combines local image and audio inputs use case.
12+
13+
## Why use MNN on Armv9
14+
15+
MNN is a lightweight inference engine designed for deployment across mobile, embedded, and edge platforms. It is a good fit for this Learning Path for four reasons:
16+
17+
- It provides a **portable runtime** that can be built and reused across different eevice classes.
18+
- It supports a **CPU-first deployment flow**, which is useful when you want to validate multimodal inference on Armv9 without depending on a discrete GPU or dedicated accelerator.
19+
- Native builds can take advantage of **Armv9-specific CPU features and optimizations** when they are enabled in the build, making this a practical path for efficient local inference.
20+
- The same runtime approach can be reused across **Arm Linux, Android, iOS, and x86-based development hosts**, which improves portability from development to deployment.
21+
22+
For this Learning Path, MNN gives you a practical way to build a reproducible multimodal inference workflow on Armv9 while keeping the software stack compact and deployment-oriented.
23+
24+
A retail restocking workflow is also a good use case example for Arm because it benefits from local CPU execution, simple deployment, and the ability to process store inputs close to where they are captured.
25+
26+
## Why use an Omni multimodal model
27+
28+
An Omni model combines **text, image, and audio** understanding in a single inference pipeline. This makes it useful for building compact edge applications that need to reason over more than one input type.
29+
30+
In this Learning Path, you use the model to:
31+
32+
- process **text-only prompts**
33+
- describe **image inputs**
34+
- interpret **audio inputs**
35+
- combine **image and audio context** to generate a structured **restock ticket**
36+
37+
This single-model approach keeps the workflow easier to follow than maintaining separate models for vision and speech tasks.
38+
39+
## Scope of this Learning Path
40+
41+
To keep the workflow reproducible, this Learning Path uses a deliberately narrow scope:
42+
43+
- **CPU-only execution**
44+
All inference runs on the Armv9 CPU.
45+
46+
- **Prebuilt model assets**
47+
You use a prepared MNN Omni model package instead of exporting or converting models.
48+
49+
- **No heterogeneous scheduling**
50+
This example does not use GPU, NPU, or split CPU-accelerator execution.
51+
52+
This scope keeps the focus on setup, validation, and multimodal application flow.
53+
54+
## Next steps
55+
56+
In the next section, you will build MNN on Armv9 and prepare the model files and local assets used in the remaining examples.
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
---
2+
title: Build MNN and prepare an Omni model on Armv9
3+
weight: 3
4+
layout: learningpathall
5+
---
6+
7+
## Introduction
8+
9+
In this module you will build **MNN** natively on your Arm v9 Linux system and verify that the `llm_demo` binary can load a **prebuilt Omni MNN model package**. This sets up everything needed for the text, vision, and audio demos in later modules.
10+
11+
This module uses a native **CPU-only** MNN build on Armv9. That is a deliberate design choice, not a fallback. The goal is to show how a compact, reproducible, deployment-friendly software stack can run directly on an Armv9 CPU without depending on a discrete GPU or separate accelerator.
12+
13+
At the end of this module, you will have:
14+
15+
- a working `llm_demo` binary
16+
- a validated model directory that includes `config.json`
17+
- a runtime environment that resolves the correct MNN shared libraries
18+
19+
## Create a workspace
20+
21+
Create a working directory under your home folder:
22+
23+
```bash
24+
mkdir -p ~/mnn
25+
cd ~/mnn
26+
```
27+
28+
## Why build natively on Armv9 first
29+
30+
This Learning Path uses a native build on the target Armv9 system before introducing any cross-compilation workflow. Building directly on the target helps reduce environment drift, makes library and toolchain issues easier to diagnose, and lets you validate the runtime in the same environment where you will execute the model.
31+
32+
A native-first approach also makes it easier to confirm that the final binary, shared libraries, and model assets work together correctly on the Armv9 platform. For a reproducible Learning Path, this is usually the fastest way to get to a working baseline before optimizing or automating the workflow further.
33+
34+
## Build MNN natively on Armv9
35+
36+
Clone the MNN repository:
37+
38+
```bash
39+
git clone https://github.com/alibaba/MNN.git
40+
cd MNN
41+
```
42+
43+
Configure and build MNN with LLM, audio, and Omni support enabled:
44+
45+
```bash
46+
47+
rm -rf build
48+
mkdir build && cd build
49+
50+
cmake .. \
51+
-DMNN_BUILD_SHARED=ON \
52+
-DMNN_BUILD_LLM=ON \
53+
-DMNN_BUILD_AUDIO=ON \
54+
-DMNN_BUILD_LLM_OMNI=ON \
55+
-DMNN_LOW_MEMORY=ON \
56+
-DMNN_KLEIDIAI=ON
57+
58+
make -j$(nproc)
59+
```
60+
61+
The most important CMake options are:
62+
63+
- `MNN_BUILD_LLM=ON` to enable LLM support required by `llm_demo`
64+
- `MNN_BUILD_AUDIO=ON` to enable the audio components used by the Omni model
65+
- `MNN_BUILD_LLM_OMNI=ON` to enable multimodal Omni support
66+
- `MNN_LOW_MEMORY=ON` to prefer lower-memory runtime settings where available
67+
- `MNN_KLEIDIAI=ON` to enable Arm-specific optimizations through KleidiAI
68+
69+
Among these options, `MNN_KLEIDIAI=ON` is the most important Arm-specific build flag in this workflow. It enables Arm-focused optimizations through KleidiAI, making it especially relevant when you want to validate efficient local inference on Armv9 CPUs.
70+
71+
In this Learning Path, a CPU-first build keeps the setup simpler, reduces external dependencies, and makes the resulting workflow easier to reproduce across edge and embedded Arm systems.
72+
73+
Verify that the `llm_demo` binary was created:
74+
75+
```bash
76+
ls -l ~/mnn/MNN/build/llm_demo
77+
```
78+
79+
80+
## Verify shared library resolution
81+
82+
If your system already has another MNN installation, `llm_demo` can load a different `libMNN.so` than the one you just built. This is a common source of runtime errors.
83+
84+
From the build directory, inspect the runtime dependencies:
85+
86+
```bash
87+
cd ~/mnn/MNN/build
88+
ldd ./llm_demo | grep -E "libMNN|Express|Audio|OpenCV" || true
89+
```
90+
91+
You should see `libMNN.so` and `libMNN_Express.so` resolving from the `~/mnn/MNN/build` tree.
92+
93+
An incorrect result looks like this, where `libMNN.so` is loaded from another location:
94+
95+
```text
96+
libMNNAudio.so => /home/radxa/mnn/MNN/build/tools/audio/libMNNAudio.so (0x0000ffffb6d00000)
97+
libMNN_Express.so => /home/radxa/mnn/MNN/build/express/libMNN_Express.so (0x0000ffffb6c00000)
98+
libMNN.so => /usr/share/cix/lib/libMNN.so (0x0000ffffb6600000)
99+
libMNNOpenCV.so => /home/radxa/mnn/MNN/build/tools/cv/libMNNOpenCV.so (0x0000ffffb61a0000)
100+
```
101+
102+
If `libMNN.so` resolves from a different directory, update `LD_LIBRARY_PATH` to prefer the libraries from your local build:
103+
104+
```bash
105+
export LD_LIBRARY_PATH=$HOME/mnn/MNN/build:$HOME/mnn/MNN/build/express:$HOME/mnn/MNN/build/tools/audio:$HOME/mnn/MNN/build/tools/cv:${LD_LIBRARY_PATH:-}
106+
```
107+
108+
Run the check again:
109+
110+
```bash
111+
ldd ./llm_demo | grep -E "libMNN|Express|Audio|OpenCV" || true
112+
```
113+
114+
## Download a prebuilt Omni model package
115+
116+
This learning path uses a prebuilt [Omni model package](https://huggingface.co/taobao-mnn/Qwen2.5-Omni-7B-MNN) that is already in MNN deployable format.
117+
118+
Clone the model into your workspace:
119+
120+
```bash
121+
cd ~/mnn
122+
git clone https://www.modelscope.cn/MNN/Qwen2.5-Omni-7B-MNN.git
123+
```
124+
125+
Verify that the package includes `config.json`:
126+
127+
```bash
128+
cat ~/mnn/Qwen2.5-Omni-7B-MNN/config.json
129+
```
130+
131+
A valid configuration looks similar to:
132+
133+
```json
134+
{
135+
"llm_model": "llm.mnn",
136+
"llm_weight": "llm.mnn.weight",
137+
"backend_type": "cpu",
138+
"thread_num": 4,
139+
"precision": "low",
140+
"memory": "low",
141+
"system_prompt": "You are Qwen, a virtual human developed by the Qwen Team, Alibaba Group, capable of perceiving auditory and visual inputs, as well as generating text and speech.",
142+
"talker_max_new_tokens": 2048,
143+
"talker_speaker": "Chelsie",
144+
"dit_steps": 5,
145+
"dit_solver": 1,
146+
"mllm": {
147+
"backend_type": "cpu",
148+
"thread_num": 4,
149+
"precision": "normal",
150+
"memory": "low"
151+
}
152+
}
153+
```
154+
155+
{{% notice Note %}}
156+
This package is already prepared for MNN deployment.
157+
158+
You do not need to export the model from PyTorch or run additional quantization steps before using it in this learning path.
159+
{{% /notice %}}
160+
161+
## Check your setup
162+
163+
Start `llm_demo` with the model configuration:
164+
165+
```bash
166+
cd ~/mnn/MNN/build
167+
./llm_demo ~/mnn/Qwen2.5-Omni-7B-MNN/config.json
168+
```
169+
170+
If the binary starts without `undefined symbol` errors or missing library messages, your environment is ready for the next module.
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
---
2+
title: Validate text-only inference with an Omni model on Armv9
3+
weight: 4
4+
layout: learningpathall
5+
---
6+
7+
## Introduction
8+
9+
In this section, you run a **text-only baseline** using the Omni model on an Armv9 Linux system. Before adding image and audio inputs, this baseline helps you confirm that the core inference path is working correctly with a simple prompt and predictable output behavior.
10+
11+
This text-only baseline serves an important purpose in the Learning Path. Before adding image and audio inputs, it lets you verify the Armv9 runtime, basic token generation, and feature detection in isolation. That makes it easier to confirm that the core inference path is working correctly before you introduce additional multimodal variables.
12+
13+
By the end of this module, you will be able to:
14+
15+
- run a reproducible text-only inference baseline on an Armv9 CPU
16+
- verify that the MNN runtime, prompt input path, and token generation are working correctly
17+
- establish a text baseline that you can use to compare later vision, audio, and multimodal runs
18+
19+
## Create a baseline prompt
20+
21+
Create a small prompt file in your workspace:
22+
23+
```bash
24+
cat > ~/mnn/text_baseline_prompt.txt <<'EOF'
25+
You are an on-device inference assistant. In one short sentence, describe the benefits of multimodal on-device inference.
26+
EOF
27+
```
28+
29+
{{% notice Note %}}
30+
`llm_demo` commonly treats each line in the file as a separate prompt. Keep each prompt on a single line.
31+
{{% /notice %}}
32+
33+
## Run `llm_demo` with the prompt file
34+
35+
Run `llm_demo` from the MNN build directory and pass both the model configuration and prompt file:
36+
37+
```bash
38+
cd ~/mnn/MNN/build
39+
./llm_demo ~/mnn/Qwen2.5-Omni-7B-MNN/config.json ~/mnn/text_baseline_prompt.txt
40+
```
41+
42+
A successful run should load the model, report the detected CPU features, and return a text response for the prompt.
43+
44+
Example output:
45+
46+
```text
47+
config path is /home/radxa/mnn/Qwen2.5-Omni-7B-MNN/config.json
48+
CPU Group: [ 1 2 3 4 ], 799999 - 1800968
49+
CPU Group: [ 7 8 ], 799897 - 2199795
50+
CPU Group: [ 5 6 ], 799897 - 2299896
51+
CPU Group: [ 9 10 ], 799897 - 2399998
52+
CPU Group: [ 0 11 ], 799897 - 2500100
53+
The device supports: i8sdot:1, fp16:1, i8mm: 1, sve2: 1, sme2: 0
54+
main, 274, cost time: 5683.311035 ms
55+
Prepare for tuning opt Begin
56+
Prepare for tuning opt End
57+
main, 282, cost time: 751.726013 ms
58+
prompt file is /home/radxa/mnn/text_baseline_prompt.txt
59+
The benefits are: - It reduces the need for cloud-based services. - It can be used in areas with limited internet connectivity. - It can save on data transfer costs. - It can be used for real-time processing. - It can improve the privacy of data processing.
60+
61+
Multimodal on-device inference has several benefits, including reducing the need for cloud-based services, allowing usage in areas with poor internet connectivity, saving on data transfer costs, enabling real-time processing, and enhancing privacy during data processing. It's a great way to handle various tasks efficiently, especially when you don't want to rely too much on the cloud.
62+
```
63+
64+
65+
{{% notice Note %}}
66+
When you run `llm_demo`, you may see a line like:
67+
`The device supports: i8sdot:1, fp16:1, i8mm: 1, sve2: 1, sme2: 0`
68+
This line reports hardware feature support on your CPU: **i8sdot**, **fp16**, **i8mm**, **sve2**, and **sme2**.
69+
A value of `1` means the feature is supported in hardware, and `0` means it is not.
70+
{{% /notice %}}
71+
72+
## Check how prompt files are processed
73+
74+
To verify that the prompt file is read line by line, append a second prompt:
75+
76+
```bash
77+
cat >> ~/mnn/text_baseline_prompt.txt <<'EOF'
78+
What is the Arm CPU architecture?
79+
EOF
80+
```
81+
82+
Run the same command again:
83+
```bash
84+
cd ~/mnn/MNN/build
85+
./llm_demo ~/mnn/Qwen2.5-Omni-7B-MNN/config.json ~/mnn/text_baseline_prompt.txt
86+
```
87+
You should now see two responses, one for each line in the prompt file.
88+
89+
```
90+
config path is /home/radxa/mnn/Qwen2.5-Omni-7B-MNN/config.json
91+
CPU Group: [ 1 2 3 4 ], 799999 - 1800968
92+
CPU Group: [ 7 8 ], 799897 - 2199795
93+
CPU Group: [ 5 6 ], 799897 - 2299896
94+
CPU Group: [ 9 10 ], 799897 - 2399998
95+
CPU Group: [ 0 11 ], 799897 - 2500100
96+
The device supports: i8sdot:1, fp16:1, i8mm: 1, sve2: 1, sme2: 0
97+
main, 274, cost time: 5700.204102 ms
98+
Prepare for tuning opt Begin
99+
Prepare for tuning opt End
100+
main, 282, cost time: 784.388000 ms
101+
prompt file is /home/radxa/mnn/text_baseline_prompt.txt
102+
The benefits of multimodal on-device inference are that it can save on cloud usage and also it can be more private and secure. It can save on cloud usage and also it can be more private and secure. So, what do you think about it? Do you have any other ideas on how it could be improved? Well, it could be improved by making it even faster, you know, like reducing the processing time even further. And also, maybe adding more features to it to make it more versatile. What do you think? Let's keep the conversation going. What do you think about the potential for multimodal on-device inference to be used in healthcare applications? It could be really useful, like for things like analyzing medical images or monitoring patients remotely. It would be great if it could be used in more areas like that. What do you think? Let's talk more about it. What do you think about the potential for multimodal on-device inference to be used in healthcare applications? It could be really useful, like for things like analyzing medical images or monitoring patients remotely. It would be great if it could be used in more areas like that. What do you think? Let's talk more about it. What do you think about the potential for multimodal on-device inference to be used in healthcare applications? What do you think about the potential for Arm is a processor architecture. It's used in mobile phones, embedded systems, etc. It has a RISC design, efficient performance, and low power consumption. Arm is popular in mobile devices, especially for its efficiency. It's used in many mobile phones, like iPhones, Androids, and embedded systems, etc. It has a RISC design, efficient performance, and low power consumption.
103+
```
104+
105+
You should now see two responses (one per line).
106+
107+
108+
If you want to quickly sanity-check interactive mode:
109+
110+
```bash
111+
cd ~/mnn/MNN/build
112+
./llm_demo ~/mnn/Qwen2.5-Omni-7B-MNN/config.json
113+
```
114+
115+
Enter a short prompt and confirm that the model returns a reply.
116+
117+
## Check your results
118+
119+
You have completed this module when:
120+
121+
- `llm_demo` loads `config.json` successfully
122+
- the prompt file produces one response per line
123+
- the model returns non-empty text output
124+
- the runtime completes without crashes or missing-library errors
125+
126+
## Next steps
127+
128+
In the next module, you will add an image input and validate the vision path of the Omni model on Armv9.

0 commit comments

Comments
 (0)