使用 Qualcomm AI Engine Direct 后端构建和运行 ExecuTorch¶
在本教程中,我们将指导您完成为 Qualcomm AI Engine Direct 构建 ExecuTorch 并在其上运行模型的过程。
Qualcomm AI Engine Direct 在源代码和文档中也称为 QNN。
在本教程中,您将学习如何降低和部署 Qualcomm AI Engine Direct 的模型。
什么是 Qualcomm AI Engine Direct?¶
Qualcomm AI Engine Direct旨在为 AI 开发提供统一的低级 API。
开发人员可以使用这组 API 与 Qualcomm SoC 上的各种加速器进行交互,包括 Kryo CPU、Adreno GPU 和 Hexagon 处理器。更多详细信息,请参见此处。
目前,此 ExecuTorch 后端可以通过 Qualcomm AI Engine Direct API 将 AI 计算委托给 Hexagon 处理器。
先决条件(硬件和软件)¶
主机操作系统¶
已验证 QNN 后端的 Linux 主机操作系统是 Ubuntu 20.04 LTS x64。
但是,由于用于下载必需 SDK(见下文)的 Qualcomm 软件包管理器 (QPM) 仅支持 Ubuntu,我们建议用户在 Ubuntu 20.04 上准确执行本教程。
硬件:¶
您需要一部运行以下 Qualcomm SoC 之一的 Android 智能手机,并连接 adb
SM8450(骁龙 8 Gen 1)
SM8475(骁龙 8 Gen 1+)
SM8550(骁龙 8 Gen 2)
SM8650(骁龙 8 Gen 3)
此示例已通过 SM8550 和 SM8450 验证。
软件:¶
遵循 ExecuTorch 推荐的 Python 版本。
用于编译 AOT 部分的编译器。已验证使用 Ubuntu20.04 的 GCC 9.4。
Android NDK。此示例已使用 NDK 25c 验证。
-
按照下载按钮操作。登录后,在工具面板中搜索 Qualcomm AI Stack。
您可以在 AI Stack 组下找到 Qualcomm AI Engine Direct SDK。
请下载 Linux 版本,并按照页面上的说明解压文件。
默认情况下,SDK 应安装在
/opt/qcom/aistack/qnn
的某个位置。将其放在其他位置也可以。我们没有关于 SDK 绝对路径的假设。
此示例已使用版本 2.12.0 验证。
已安装 Qualcomm AI Engine Direct SDK 的目录如下所示
$ tree -L 1 /opt/qcom/aistack/qnn/<version>/
/opt/qcom/aistack/qnn/<version>/
├── benchmarks
├── bin
├── docs
├── examples
├── include
├── lib
├── LICENSE.pdf
├── QNN_NOTICE.txt
├── QNN_README.txt
├── QNN_ReleaseNotes.txt
├── share
└── Uninstall
设置您的开发环境¶
约定¶
$QNN_SDK_ROOT
指 Qualcomm AI Engine Direct SDK 的根目录,即包含 QNN_README.txt
的目录。
$ANDROID_NDK
指 Android NDK 的根目录。
$EXECUTORCH_ROOT
指 executorch git 存储库的根目录。
设置环境变量¶
我们设置 LD_LIBRARY_PATH
以确保动态链接程序可以找到 QNN 库。
此外,我们设置 PYTHONPATH
,因为这样可以更轻松地开发和导入 ExecuTorch Python API。
export LD_LIBRARY_PATH=$QNN_SDK_ROOT/lib/x86_64-linux-clang/:$LD_LIBRARY_PATH
export PYTHONPATH=$EXECUTORCH_ROOT/..
构建¶
以下构建说明的示例脚本在此处。
AOT(预先)组件:¶
需要 x64 上的 Python API 才能将模型编译为 Qualcomm AI Engine Direct 二进制文件。
cd $EXECUTORCH_ROOT
# Workaround for fbs files in exir/_serialize
cp schema/program.fbs exir/_serialize/program.fbs
cp schema/scalar_type.fbs exir/_serialize/scalar_type.fbs
mkdir build_x86_64
cd build_x86_64
cmake .. -DEXECUTORCH_BUILD_QNN=ON -DQNN_SDK_ROOT=${QNN_SDK_ROOT}
cmake --build . -t "PyQnnManagerAdaptor" "PyQnnWrapperAdaptor" -j8
# install Python APIs to correct import path
# The filename might vary depending on your Python and host version.
cp -f backends/qualcomm/PyQnnManagerAdaptor.cpython-310-x86_64-linux-gnu.so $EXECUTORCH_ROOT/backends/qualcomm/python
cp -f backends/qualcomm/PyQnnWrapperAdaptor.cpython-310-x86_64-linux-gnu.so $EXECUTORCH_ROOT/backends/qualcomm/python
运行时:¶
一个示例 qnn_executor_runner
可执行文件将用于运行已编译的 pte
模型。
为 Android 构建 qnn_executor_runner
的命令
cd $EXECUTORCH_ROOT
mkdir build_android
cd build_android
# build executorch & qnn_executorch_backend
cmake .. \
-DCMAKE_INSTALL_PREFIX=$PWD \
-DEXECUTORCH_BUILD_SDK=ON \
-DEXECUTORCH_BUILD_QNN=ON \
-DQNN_SDK_ROOT=$QNN_SDK_ROOT \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI='arm64-v8a' \
-DANDROID_NATIVE_API_LEVEL=23 \
-B$PWD
cmake --build $PWD -j16 --target install
cmake ../examples/qualcomm \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI='arm64-v8a' \
-DANDROID_NATIVE_API_LEVEL=23 \
-DCMAKE_PREFIX_PATH="$PWD/lib/cmake/ExecuTorch;$PWD/third-party/gflags;" \
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH \
-Bexamples/qualcomm
cmake --build examples/qualcomm -j16
注意:如果您想构建发行版,请将 -DCMAKE_BUILD_TYPE=Release
添加到 cmake
命令选项。
您可以在 build_android/examples/qualcomm/
下找到 qnn_executor_runner
。
在设备上部署和运行¶
AOT 编译模型¶
您可以参考 此脚本 了解确切流程。在本教程中,我们使用 deeplab-v3-resnet101 作为示例。运行以下命令进行编译
cd $EXECUTORCH_ROOT
python -m examples.qualcomm.scripts.deeplab_v3 -b build_android -m SM8550 --compile_only --download
您可能会看到如下内容
[INFO][Qnn ExecuTorch] Destroy Qnn context
[INFO][Qnn ExecuTorch] Destroy Qnn device
[INFO][Qnn ExecuTorch] Destroy Qnn backend
opcode name target args kwargs
------------- ------------------------ --------------------------- ----------------------------- --------
placeholder arg684_1 arg684_1 () {}
get_attr lowered_module_0 lowered_module_0 () {}
call_function executorch_call_delegate executorch_call_delegate (lowered_module_0, arg684_1) {}
call_function getitem <built-in function getitem> (executorch_call_delegate, 0) {}
call_function getitem_1 <built-in function getitem> (executorch_call_delegate, 1) {}
output output output ([getitem_1, getitem],) {}
已编译的模型是 ./deeplab_v3/dlv3_qnn.pte
。
在搭载 Qualcomm SoC 的 Android 智能手机上运行模型推理¶
步骤 1。我们需要将必需的 QNN 库推送到设备。
# make sure you have write-permission on below path.
DEVICE_DIR=/data/local/tmp/executorch_qualcomm_tutorial/
adb shell "mkdir -p ${DEVICE_DIR}"
adb push ${QNN_SDK_ROOT}/lib/aarch64-android/libQnnHtp.so ${DEVICE_DIR}
adb push ${QNN_SDK_ROOT}/lib/aarch64-android/libQnnHtpV69Stub.so ${DEVICE_DIR}
adb push ${QNN_SDK_ROOT}/lib/aarch64-android/libQnnHtpV73Stub.so ${DEVICE_DIR}
adb push ${QNN_SDK_ROOT}/lib/aarch64-android/libQnnSystem.so ${DEVICE_DIR}
adb push ${QNN_SDK_ROOT}/lib/hexagon-v69/unsigned/libQnnHtpV69Skel.so ${DEVICE_DIR}
adb push ${QNN_SDK_ROOT}/lib/hexagon-v73/unsigned/libQnnHtpV73Skel.so ${DEVICE_DIR}
步骤 2。我们还需要通过设置 ADSP_LIBRARY_PATH
和 LD_LIBRARY_PATH
指示 Android 和 Hexagon 上的动态链接器在哪里可以找到这些库。因此,我们可以像这样运行 qnn_executor_runner
adb push ./deeplab_v3/dlv3_qnn.pte ${DEVICE_DIR}
adb push ${EXECUTORCH_ROOT}/build_android/examples/qualcomm/qnn_executor_runner ${DEVICE_DIR}
adb push ${EXECUTORCH_ROOT}/build_android/lib/libqnn_executorch_backend.so ${DEVICE_DIR}
adb shell "cd ${DEVICE_DIR} \
&& export LD_LIBRARY_PATH=${DEVICE_DIR} \
&& export ADSP_LIBRARY_PATH=${DEVICE_DIR} \
&& ./qnn_executor_runner --model_path ./dlv3_qnn.pte"
您应该看到如下内容
I 00:00:01.835706 executorch:qnn_executor_runner.cpp:298] 100 inference took 1096.626000 ms, avg 10.966260 ms
[INFO][Qnn ExecuTorch] Destroy Qnn backend parameters
[INFO][Qnn ExecuTorch] Destroy Qnn context
[INFO][Qnn ExecuTorch] Destroy Qnn device
[INFO][Qnn ExecuTorch] Destroy Qnn backend
即将推出¶
使用量化 mobilebert 的示例 来解决多类文本分类问题。
更多 Qualcomm AI Engine Direct 加速器,例如 GPU。
常见问题解答¶
如果您在重现教程时遇到任何问题,请在 ExecuTorch 仓库中提交一个 github 问题,并标记使用 #qcom_aisw
标记