Skip to content

Commit 864e27e

Browse files
committed
Qualcomm AI Engine Direct - LE support
Summary: - enable linux embedded support for toolchain: aarch64-oe-linux-gcc9.3 (SXR1230P) - update document a bit
1 parent 0b8d99f commit 864e27e

File tree

6 files changed

+175
-20
lines changed

6 files changed

+175
-20
lines changed

backends/qualcomm/aot/ir/qcir_utils.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,9 @@ Qnn_Tensor_t ToTensor(const tensor_type& tensor, const uint8_t* data_ptr) {
322322
return type < QNN_TENSOR_TYPE_STATIC;
323323
};
324324

325-
Qnn_Tensor_t t({.version = QNN_TENSOR_VERSION_2, .v2 = QNN_TENSOR_V2_INIT});
325+
Qnn_Tensor_t t;
326+
t.version = QNN_TENSOR_VERSION_2;
327+
t.v2 = QNN_TENSOR_V2_INIT;
326328
QNN_TENSOR_VER_PTR(t)->name = tensor->name()->c_str();
327329
QNN_TENSOR_VER_PTR(t)->type = ToTensorType(tensor->type());
328330
QNN_TENSOR_VER_PTR(t)->dataType = ToDataType(tensor->dtype());

backends/qualcomm/scripts/build.sh

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ fi
1616
usage() {
1717
echo "Usage: Build the aarch64 version of executor runner or the python interface of Qnn Manager"
1818
echo "First, you need to set the environment variable for QNN_SDK_ROOT"
19-
echo ", and if you want to build the aarch64 version of executor runner"
19+
echo ", and if you want to build the android version of executor runner"
2020
echo ", you need to export ANDROID_NDK_ROOT=/path/to/android_ndkXX"
21+
echo "(or export TOOLCHAIN_ROOT_HOST=/path/to/sysroots/xx_host, "
22+
echo "TOOLCHAIN_ROOT_TARGET=/path/to/sysroots/xx_target for linux embedded with --le)"
2123
echo "e.g.: executorch$ ./backends/qualcomm/scripts/build.sh --skip_x86_64"
2224
exit 1
2325
}
@@ -27,8 +29,10 @@ usage() {
2729

2830
BUILD_X86_64="true"
2931
CMAKE_X86_64="build-x86"
30-
BUILD_AARCH64="true"
31-
CMAKE_AARCH64="build-android"
32+
BUILD_ANDROID="true"
33+
CMAKE_ANDROID="build-android"
34+
BUILD_OE_LINUX="false"
35+
CMAKE_OE_LINUX="build-oe-linux"
3236
CLEAN="true"
3337
BUILD_TYPE="RelWithDebInfo"
3438
BUILD_JOB_NUMBER="16"
@@ -41,7 +45,7 @@ if [ -z BUCK2 ]; then
4145
BUCK2="buck2"
4246
fi
4347

44-
long_options=skip_x86_64,skip_aarch64,no_clean,release,job_number:
48+
long_options=skip_x86_64,skip_la,skip_le,le,no_clean,release,job_number:
4549

4650
parsed_args=$(getopt -a --options '' --longoptions $long_options --name "$0" -- "$@")
4751
eval set -- "$parsed_args"
@@ -50,7 +54,9 @@ eval set -- "$parsed_args"
5054
while true ; do
5155
case "$1" in
5256
--skip_x86_64) BUILD_X86_64="false"; shift;;
53-
--skip_aarch64) BUILD_AARCH64="false"; shift;;
57+
--skip_la) BUILD_ANDROID="false"; shift;;
58+
--skip_le) BUILD_OE_LINUX="false"; shift;;
59+
--le) BUILD_ANDROID="false"; BUILD_OE_LINUX="true"; shift;;
5460
--no_clean) CLEAN="false"; shift;;
5561
--release) BUILD_TYPE="Release"; shift;;
5662
--job_number) BUILD_JOB_NUMBER="$2"; shift 2;;
@@ -60,13 +66,13 @@ done
6066

6167
PRJ_ROOT="$( cd "$(dirname "$0")/../../.." ; pwd -P)"
6268

63-
if [ "$BUILD_AARCH64" = true ]; then
69+
if [ "$BUILD_ANDROID" = true ]; then
6470
if [[ -z ${ANDROID_NDK_ROOT} ]]; then
6571
echo "Please export ANDROID_NDK_ROOT=/path/to/android_ndkXX"
6672
exit -1
6773
fi
6874

69-
BUILD_ROOT=$PRJ_ROOT/$CMAKE_AARCH64
75+
BUILD_ROOT=$PRJ_ROOT/$CMAKE_ANDROID
7076
if [ "$CLEAN" = true ]; then
7177
rm -rf $BUILD_ROOT && mkdir $BUILD_ROOT
7278
else
@@ -112,6 +118,70 @@ if [ "$BUILD_AARCH64" = true ]; then
112118
cmake --build $EXAMPLE_ROOT -j$BUILD_JOB_NUMBER
113119
fi
114120

121+
if [ "$BUILD_OE_LINUX" = true ]; then
122+
if [[ -z ${TOOLCHAIN_ROOT_HOST} ]]; then
123+
echo "Please export e.g. TOOLCHAIN_ROOT_HOST=/path/to/sysroots/x86_64-qtisdk-linux"
124+
exit -1
125+
fi
126+
if [[ -z ${TOOLCHAIN_ROOT_TARGET} ]]; then
127+
echo "Please export e.g. TOOLCHAIN_ROOT_TARGET=/path/to/sysroots/armv8a-oe-linux"
128+
exit -1
129+
fi
130+
131+
BUILD_ROOT=$PRJ_ROOT/$CMAKE_OE_LINUX
132+
if [ "$CLEAN" = true ]; then
133+
rm -rf $BUILD_ROOT && mkdir $BUILD_ROOT
134+
else
135+
# Force rebuild flatccrt for the correct platform
136+
cd $BUILD_ROOT/third-party/flatcc && make clean
137+
fi
138+
139+
TOOLCHAN_PREFIX=$TOOLCHAIN_ROOT_HOST/usr/bin/aarch64-oe-linux/aarch64-oe-linux-
140+
cd $BUILD_ROOT
141+
cmake .. \
142+
-DCMAKE_INSTALL_PREFIX=$BUILD_ROOT \
143+
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
144+
-DCMAKE_C_COMPILER=${TOOLCHAN_PREFIX}gcc \
145+
-DCMAKE_CXX_COMPILER=${TOOLCHAN_PREFIX}g++ \
146+
-DCMAKE_SYSROOT=$TOOLCHAIN_ROOT_TARGET \
147+
-DCMAKE_SYSTEM_NAME=Linux \
148+
-DCMAKE_SYSTEM_PROCESSOR=aarch64 \
149+
-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \
150+
-DEXECUTORCH_BUILD_CPUINFO=OFF \
151+
-DEXECUTORCH_BUILD_QNN=ON \
152+
-DEXECUTORCH_BUILD_DEVTOOLS=ON \
153+
-DEXECUTORCH_BUILD_EXTENSION_MODULE=ON \
154+
-DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \
155+
-DEXECUTORCH_BUILD_EXTENSION_FLAT_TENSOR=ON \
156+
-DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON \
157+
-DEXECUTORCH_ENABLE_EVENT_TRACER=ON \
158+
-DQNN_SDK_ROOT=$QNN_SDK_ROOT \
159+
-DEXECUTORCH_BUILD_KERNELS_QUANTIZED=ON \
160+
-DPYTHON_EXECUTABLE=$PYTHON_EXECUTABLE \
161+
-B$BUILD_ROOT
162+
163+
cmake --build $BUILD_ROOT -j$BUILD_JOB_NUMBER --target install
164+
165+
EXAMPLE_ROOT=examples/qualcomm
166+
CMAKE_PREFIX_PATH="${BUILD_ROOT}/lib/cmake/ExecuTorch;${BUILD_ROOT}/third-party/gflags;"
167+
168+
cmake $PRJ_ROOT/$EXAMPLE_ROOT \
169+
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
170+
-DCMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH \
171+
-DCMAKE_C_COMPILER=${TOOLCHAN_PREFIX}gcc \
172+
-DCMAKE_CXX_COMPILER=${TOOLCHAN_PREFIX}g++ \
173+
-DCMAKE_SYSROOT=$TOOLCHAIN_ROOT_TARGET \
174+
-DCMAKE_SYSTEM_NAME=Linux \
175+
-DCMAKE_SYSTEM_PROCESSOR=aarch64 \
176+
-DEXECUTORCH_BUILD_KERNELS_QUANTIZED=ON \
177+
-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \
178+
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH \
179+
-DPYTHON_EXECUTABLE=$PYTHON_EXECUTABLE \
180+
-B$EXAMPLE_ROOT
181+
182+
cmake --build $EXAMPLE_ROOT -j$BUILD_JOB_NUMBER
183+
fi
184+
115185
if [ "$BUILD_X86_64" = true ]; then
116186
BUILD_ROOT=$PRJ_ROOT/$CMAKE_X86_64
117187
if [ "$CLEAN" = true ]; then

backends/qualcomm/tests/test_qnn_delegate.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5988,7 +5988,13 @@ def setup_environment():
59885988
default="",
59895989
type=str,
59905990
)
5991-
5991+
parser.add_argument(
5992+
"-t",
5993+
"--target",
5994+
help="Target platform for deployment",
5995+
default="aarch64-android",
5996+
type=str,
5997+
)
59925998
parser.add_argument(
59935999
"--pre_gen_pte",
59946000
help="Run the pre-generated pte in the given directory.",
@@ -6023,6 +6029,7 @@ def setup_environment():
60236029
TestQNN.pre_gen_pte = args.pre_gen_pte
60246030
TestQNN.llama_artifacts = args.llama_artifacts
60256031
TestQNN.op_package_dir = args.op_package_dir
6032+
TestQNN.target = args.target
60266033
return sys.argv[:1] + ns_args
60276034

60286035

backends/qualcomm/tests/utils.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,10 +188,13 @@ class TestQNN(unittest.TestCase):
188188
pretrained_weight: str = ""
189189
enable_profile: bool = False
190190
op_package_dir: str = ""
191+
target: str = ""
192+
model_name: str = ""
191193
online_prepare: bool = False
192194
use_8a8w: str = "8a8w"
193195
use_16a16w: str = "16a16w"
194196
use_16a4w: str = "16a4w"
197+
oss_repo: str = ""
195198
shared_buffer: bool = False
196199
enable_x86_64: bool = False
197200
compile_only: bool = False
@@ -432,6 +435,7 @@ def validate_intermediate_tensor():
432435
if check_io_shape
433436
else None
434437
),
438+
target=self.target,
435439
)
436440
adb.push(
437441
inputs=[processed_inputs],
@@ -616,6 +620,7 @@ def get_adb_tool(self, pte_fname):
616620
host_id=self.host,
617621
soc_model=self.model,
618622
error_only=self.error_only,
623+
target=self.target,
619624
)
620625
return adb
621626

docs/source/backends-qualcomm.md

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ For more details and troubleshooting, refer to the official Microsoft WSL instal
5353
👉 [Install WSL | Microsoft Learn](https://learn.microsoft.com/en-us/windows/wsl/install)
5454

5555
### Hardware:
56-
You will need an Android smartphone with adb-connected running on one of below Qualcomm SoCs:
56+
You will need an Android / Linux device with adb-connected running on one of below Qualcomm SoCs:
5757
- SA8295
5858
- SM8450 (Snapdragon 8 Gen 1)
5959
- SM8475 (Snapdragon 8 Gen 1+)
@@ -62,7 +62,7 @@ You will need an Android smartphone with adb-connected running on one of below Q
6262
- SM8750 (Snapdragon 8 Elite)
6363
- SSG2115P
6464
- SSG2125P
65-
- SXR1230P
65+
- SXR1230P (Linux Embedded)
6666
- SXR2230P
6767
- SXR2330P
6868

@@ -73,6 +73,7 @@ This example is verified with SM8550 and SM8450.
7373
- Follow ExecuTorch recommended Python version.
7474
- A compiler to compile AOT parts, e.g., the GCC compiler comes with Ubuntu LTS.
7575
- [Android NDK](https://developer.android.com/ndk). This example is verified with NDK 26c.
76+
- (Optional) Target toolchain for linux embedded platform.
7677
- [Qualcomm AI Engine Direct SDK](https://developer.qualcomm.com/software/qualcomm-ai-engine-direct-sdk)
7778
- Click the "Get Software" button to download a version of QNN SDK.
7879
- However, at the moment of updating this tutorial, the above website doesn't provide QNN SDK newer than 2.22.6.
@@ -131,8 +132,11 @@ The above script is actively used. It is updated more frquently than this tutori
131132
An example usage is
132133
```bash
133134
cd $EXECUTORCH_ROOT
135+
# android target
134136
./backends/qualcomm/scripts/build.sh
135-
# or
137+
# (optional) linux embedded target
138+
./backends/qualcomm/scripts/build.sh --le
139+
# for release build
136140
./backends/qualcomm/scripts/build.sh --release
137141
```
138142

@@ -148,11 +152,14 @@ cd build-x86
148152
# Please refer to the above build.sh for latest workable commands.
149153
cmake .. \
150154
-DCMAKE_INSTALL_PREFIX=$PWD \
155+
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
151156
-DEXECUTORCH_BUILD_QNN=ON \
152157
-DQNN_SDK_ROOT=${QNN_SDK_ROOT} \
153158
-DEXECUTORCH_BUILD_DEVTOOLS=ON \
154159
-DEXECUTORCH_BUILD_EXTENSION_MODULE=ON \
155160
-DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON \
161+
-DEXECUTORCH_BUILD_EXTENSION_FLAT_TENSOR=ON \
162+
-DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \
156163
-DEXECUTORCH_ENABLE_EVENT_TRACER=ON \
157164
-DPYTHON_EXECUTABLE=python3
158165

@@ -177,17 +184,23 @@ A example `qnn_executor_runner` executable would be used to run the compiled `pt
177184
Commands to build `qnn_executor_runner` for Android:
178185

179186
```bash
187+
export ANDROID_NDK_ROOT=/path/to/android_ndk_r26c/..
188+
180189
cd $EXECUTORCH_ROOT
181190
mkdir build-android
182191
cd build-android
183192
# build executorch & qnn_executorch_backend
184193
cmake .. \
185194
-DCMAKE_INSTALL_PREFIX=$PWD \
195+
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
186196
-DEXECUTORCH_BUILD_QNN=ON \
187197
-DQNN_SDK_ROOT=$QNN_SDK_ROOT \
188198
-DEXECUTORCH_BUILD_DEVTOOLS=ON \
189199
-DEXECUTORCH_BUILD_EXTENSION_MODULE=ON \
190200
-DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON \
201+
-DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \
202+
-DEXECUTORCH_BUILD_EXTENSION_FLAT_TENSOR=ON \
203+
-DEXECUTORCH_BUILD_KERNELS_QUANTIZED=ON \
191204
-DEXECUTORCH_ENABLE_EVENT_TRACER=ON \
192205
-DPYTHON_EXECUTABLE=python3 \
193206
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_ROOT/build/cmake/android.toolchain.cmake \
@@ -199,6 +212,7 @@ cmake .. \
199212
cmake --build $PWD --target install -j$(nproc)
200213

201214
cmake ../examples/qualcomm \
215+
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
202216
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_ROOT/build/cmake/android.toolchain.cmake \
203217
-DANDROID_ABI='arm64-v8a' \
204218
-DANDROID_PLATFORM=android-30 \
@@ -214,6 +228,61 @@ cmake --build examples/qualcomm -j$(nproc)
214228
ls examples/qualcomm
215229
```
216230

231+
(Optional) Commands to build `qnn_executor_runner` for Linux Embedded:
232+
233+
```bash
234+
export TOOLCHAIN_ROOT_HOST=/path/to/sysroots/HOST # e.g. x86_64-qtisdk-linux
235+
export TOOLCHAIN_ROOT_TARGET=/path/to/sysroots/TARGET # e.g. armv8a-oe-linux
236+
237+
cd $EXECUTORCH_ROOT
238+
mkdir build-oe-linux
239+
cd build-oe-linux
240+
# build executorch & qnn_executorch_backend
241+
cmake .. \
242+
-DCMAKE_INSTALL_PREFIX=$PWD \
243+
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
244+
-DCMAKE_C_COMPILER=${TOOLCHAIN_ROOT_HOST}/usr/bin/aarch64-oe-linux/aarch64-oe-linux-gcc \
245+
-DCMAKE_CXX_COMPILER=${TOOLCHAIN_ROOT_HOST}/usr/bin/aarch64-oe-linux/aarch64-oe-linux-g++ \
246+
-DCMAKE_SYSROOT=$TOOLCHAIN_ROOT_TARGET \
247+
-DCMAKE_SYSTEM_NAME=Linux \
248+
-DCMAKE_SYSTEM_PROCESSOR=aarch64 \
249+
-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \
250+
-DEXECUTORCH_BUILD_CPUINFO=OFF \
251+
-DEXECUTORCH_BUILD_QNN=ON \
252+
-DQNN_SDK_ROOT=$QNN_SDK_ROOT \
253+
-DEXECUTORCH_BUILD_DEVTOOLS=ON \
254+
-DEXECUTORCH_BUILD_EXTENSION_MODULE=ON \
255+
-DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON \
256+
-DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \
257+
-DEXECUTORCH_BUILD_EXTENSION_FLAT_TENSOR=ON \
258+
-DEXECUTORCH_BUILD_KERNELS_QUANTIZED=ON \
259+
-DEXECUTORCH_ENABLE_EVENT_TRACER=ON \
260+
-DPYTHON_EXECUTABLE=python3 \
261+
262+
# nproc is used to detect the number of available CPU.
263+
# If it is not applicable, please feel free to use the number you want.
264+
cmake --build $PWD --target install -j$(nproc)
265+
266+
cmake ../examples/qualcomm \
267+
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
268+
-DCMAKE_PREFIX_PATH="$PWD/lib/cmake/ExecuTorch;$PWD/third-party/gflags;" \
269+
-DCMAKE_C_COMPILER=${TOOLCHAIN_ROOT_HOST}/usr/bin/aarch64-oe-linux/aarch64-oe-linux-gcc \
270+
-DCMAKE_CXX_COMPILER=${TOOLCHAIN_ROOT_HOST}/usr/bin/aarch64-oe-linux/aarch64-oe-linux-g++ \
271+
-DCMAKE_SYSROOT=$TOOLCHAIN_ROOT_TARGET \
272+
-DCMAKE_SYSTEM_NAME=Linux \
273+
-DCMAKE_SYSTEM_PROCESSOR=aarch64 \
274+
-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \
275+
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH \
276+
-DPYTHON_EXECUTABLE=python3 \
277+
-Bexamples/qualcomm
278+
279+
cmake --build examples/qualcomm -j$(nproc)
280+
281+
# qnn_executor_runner can be found under examples/qualcomm
282+
# The full path is $EXECUTORCH_ROOT/build-oe-linux/examples/qualcomm/qnn_executor_runner
283+
ls examples/qualcomm
284+
```
285+
217286
**Note:** If you want to build for release, add `-DCMAKE_BUILD_TYPE=Release` to the `cmake` command options.
218287

219288

@@ -351,7 +420,10 @@ I 00:00:00.364875 executorch:qnn_executor_runner.cpp:425] Write etdump to etdump
351420
The model is merely executed. If we want to feed real inputs and get model outputs, we can use
352421
```bash
353422
cd $EXECUTORCH_ROOT
423+
# android
354424
python -m examples.qualcomm.scripts.deeplab_v3 -b build-android -m SM8550 --download -s <device_serial>
425+
# (optional) linux embedded
426+
python -m examples.qualcomm.scripts.deeplab_v3 -b build-oe-linux -m SXR1230P --download -s <device_serial> -t aarch64-oe-linux-gcc-9.3
355427
```
356428
The `<device_serial>` can be found by `adb devices` command.
357429

examples/qualcomm/utils.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ def __init__(
8181
shared_buffer=False,
8282
dump_intermediate_outputs=False,
8383
runner="examples/qualcomm/executor_runner/qnn_executor_runner",
84+
target="aarch64-android",
8485
expected_input_shape=None,
8586
expected_output_shape=None,
8687
):
@@ -100,6 +101,7 @@ def __init__(
100101
self.error_only = error_only
101102
self.shared_buffer = shared_buffer
102103
self.runner = runner
104+
self.target = target
103105
self.expected_input_shape = expected_input_shape
104106
self.expected_output_shape = expected_output_shape
105107
self.extra_cmds = ""
@@ -122,20 +124,17 @@ def push(self, inputs=None, input_list=None, files=None):
122124
# necessary artifacts
123125
artifacts = [
124126
*self.pte_path,
125-
f"{self.qnn_sdk}/lib/aarch64-android/libQnnHtp.so",
127+
f"{self.qnn_sdk}/lib/{self.target}/libQnnHtp.so",
126128
(
127129
f"{self.qnn_sdk}/lib/hexagon-v{self.htp_arch}/"
128130
f"unsigned/libQnnHtpV{self.htp_arch}Skel.so"
129131
),
130-
(
131-
f"{self.qnn_sdk}/lib/aarch64-android/"
132-
f"libQnnHtpV{self.htp_arch}Stub.so"
133-
),
134-
f"{self.qnn_sdk}/lib/aarch64-android/libQnnHtpPrepare.so",
135-
f"{self.qnn_sdk}/lib/aarch64-android/libQnnSystem.so",
132+
(f"{self.qnn_sdk}/lib/{self.target}/" f"libQnnHtpV{self.htp_arch}Stub.so"),
133+
f"{self.qnn_sdk}/lib/{self.target}/libQnnHtpPrepare.so",
134+
f"{self.qnn_sdk}/lib/{self.target}/libQnnSystem.so",
136135
f"{self.build_path}/{self.runner}",
137136
f"{self.build_path}/backends/qualcomm/libqnn_executorch_backend.so",
138-
f"{self.qnn_sdk}/lib/aarch64-android/libQnnModelDlc.so",
137+
f"{self.qnn_sdk}/lib/{self.target}/libQnnModelDlc.so",
139138
]
140139
input_list_file, input_files = generate_inputs(
141140
self.working_dir, self.input_list_filename, inputs, input_list

0 commit comments

Comments
 (0)