Skip to content

Commit

Permalink
[QNN EP] Update QNN SDK to 2.21 (#20534)
Browse files Browse the repository at this point in the history
### Description
- Updates QNN pipelines to use QNN SDK 2.21
- Downloads QNN SDK from Azure storage to avoid having to rebuild images
when a new version is released.


### Motivation and Context
Test with the latest QNN SDK.
  • Loading branch information
adrianlizarraga authored May 2, 2024
1 parent 8707655 commit 0dda8b0
Show file tree
Hide file tree
Showing 14 changed files with 105 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,10 @@ Status ResizeOpBuilder::IsOpSupported(QnnModelWrapper& qnn_model_wrapper,
// nearest_mode:
// coordinate_transformation_mode: | round_prefer_floor round_prefer_ceil floor ceil
// -----------------------------------------------------------------------------------------
// half_pixel | Resize X RNN X
// pytorch_half_pixel | Resize X X X
// align_corners | Resize X RNN X
// asymmetric | Resize X RNN X
// half_pixel | Resize(QNN < 2.20) X RNN X
// pytorch_half_pixel | Resize(QNN < 2.20) X X X
// align_corners | Resize(QNN < 2.20) Resize(QNN 2.20) RNN X
// asymmetric | Resize(QNN < 2.20) X RNN X

if (interp_mode == "nearest") {
const std::string nearest_mode = GetOnnxAttr(node_helper, onnx_nearest_mode_attr);
Expand All @@ -181,13 +181,16 @@ Status ResizeOpBuilder::IsOpSupported(QnnModelWrapper& qnn_model_wrapper,

if (is_npu_backend) {
// QNN only supports the following nearest_mode values on HTP:
// - "round_prefer_floor" via QNN's Resize operator
// - QNN 2.19: "round_prefer_floor" via QNN's Resize operator
// - QNN 2.20 (API version 2.14): "round_prefer_ceil" via QNN's Resize operator
// - "floor" via QNN's ResizeNearestNeighbor operator
//
// QNN validation does not throw an error if unsupported nearest_mode values are used, so we have to
// catch them here. Otherwise, accuracy is significantly degraded.
#if QNN_API_VERSION_MAJOR >= 2 && QNN_API_VERSION_MINOR >= 14
ORT_RETURN_IF_NOT(nearest_mode == "round_prefer_ceil" || nearest_mode == "floor",
"QNN EP: Resize on the NPU does not support nearest_mode ", nearest_mode.c_str());
#else
ORT_RETURN_IF_NOT(nearest_mode == "round_prefer_floor" || nearest_mode == "floor",
"QNN EP: Resize on the NPU does not support nearest_mode ", nearest_mode.c_str());
#endif

const bool use_resize_nn_op = nearest_mode == "floor";

Expand All @@ -200,6 +203,13 @@ Status ResizeOpBuilder::IsOpSupported(QnnModelWrapper& qnn_model_wrapper,
// QNN's ResizeNearestNeighbor requires rank 4 inputs.
ORT_RETURN_IF(use_resize_nn_op && input_rank != 4,
"QNN EP: Resize on the NPU with nearest_mode == 'floor' requires an input with rank 4.");

#if QNN_API_VERSION_MAJOR >= 2 && QNN_API_VERSION_MINOR >= 14
// QNN's Resize only supports "round_prefer_ceil" if transformation_mode is "align_corners".
ORT_RETURN_IF(!use_resize_nn_op && transformation_mode != "align_corners",
"QNN EP: Resize on the NPU only supports 'round_prefer_ceil' if "
"transformation mode is 'align_corners'");
#endif
}
}

Expand Down
18 changes: 15 additions & 3 deletions onnxruntime/test/providers/qnn/resize_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -394,10 +394,21 @@ TEST_F(QnnHTPBackendTests, ResizeU8_2xLinearAsymmetric) {

// Test 2x QDQ Resize mode: "nearest", coordinate_transformation_mode: "half_pixel", nearest_mode: "round_prefer_floor"
// Maps to QNN's Resize operator.
TEST_F(QnnHTPBackendTests, ResizeU8_2xNearestHalfPixelRoundPreferFloor) {
// UPDATE: "round_prefer_floor" no longer supported in QNN SDK 2.21 (supported in QNN SDK 2.19)
TEST_F(QnnHTPBackendTests, ResizeU8_2xNearestHalfPixelRoundPreferFloor_Unsupported) {
std::vector<float> input_data = GetFloatDataInRange(-10.0f, 10.0f, 48);
RunQDQResizeOpTest<uint8_t>(TestInputDef<float>({1, 3, 4, 4}, false, input_data),
{1, 3, 8, 8}, "nearest", "half_pixel", "round_prefer_floor",
ExpectedEPNodeAssignment::None); // No longer supported as of QNN SDK 2.21
}

// Test 2x QDQ Resize mode: "nearest", coordinate_transformation_mode: "align_corners", nearest_mode: "round_prefer_ceil"
// Maps to QNN's Resize operator.
// UPDATE: "round_prefer_ceil" is supported as of QNN SDK 2.21 if using "align_corners". (Unsupported in QNN SDK 2.19).
TEST_F(QnnHTPBackendTests, ResizeU8_2xNearestAlignCornersRoundPreferCeil) {
std::vector<float> input_data = GetFloatDataInRange(-10.0f, 10.0f, 48);
RunQDQResizeOpTest<uint8_t>(TestInputDef<float>({1, 3, 4, 4}, false, input_data),
{1, 3, 8, 8}, "nearest", "align_corners", "round_prefer_ceil",
ExpectedEPNodeAssignment::All);
}

Expand All @@ -420,11 +431,12 @@ TEST_F(QnnHTPBackendTests, ResizeU8_3xNearestAsymmetricFloor) {

// Test 2x QDQ Resize mode: "nearest", coordinate_transformation_mode: "asymmetric", nearest_mode: "round_prefer_floor"
// Maps to QNN's Resize operator.
TEST_F(QnnHTPBackendTests, ResizeU8_2xNearestAsymmetricRoundPreferFloor) {
// UPDATE: "round_prefer_floor" no longer supported in QNN SDK 2.21 (supported in QNN SDK 2.19)
TEST_F(QnnHTPBackendTests, ResizeU8_2xNearestAsymmetricRoundPreferFloor_Unsupported) {
std::vector<float> input_data = GetFloatDataInRange(-10.0f, 10.0f, 8);
RunQDQResizeOpTest<uint8_t>(TestInputDef<float>({1, 2, 2, 2}, false, input_data),
{1, 2, 4, 4}, "nearest", "asymmetric", "round_prefer_floor",
ExpectedEPNodeAssignment::All);
ExpectedEPNodeAssignment::None); // No longer supported as of QNN SDK 2.21
}

// Test 3x QDQ Resize mode: "nearest", coordinate_transformation_mode: "asymmetric", nearest_mode: "round_prefer_floor"
Expand Down
8 changes: 7 additions & 1 deletion onnxruntime/test/providers/qnn/simple_op_htp_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,13 @@ TEST_F(QnnHTPBackendTests, UnaryOp_Ceil) {
}

// Test accuracy of 16-bit QDQ Ceil op.
TEST_F(QnnHTPBackendTests, UnaryOp_Ceil_U16) {
// TODO(adrianlizarraga): Fails in QNN SDK 2.21 (linux). On Windows ARM64, fails in QNN SDK 2.19.
//
// input: [-12.0, -7.199, -2.399, 2.4, 7.2, 12.0]
// CPU EP f32 model output: [-12.0, -7.0, -2.0, 3.0, 8.0, 12.0]
// CPU EP qdq model output: [-12.0, -6.99, -1.99, 3.0, 8.0, 11.99]
// QNN EP qdq model output: [-11.0 (WRONG), -7.0, -2.0, 2.99, 8.0, 11.99]
TEST_F(QnnHTPBackendTests, DISABLED_UnaryOp_Ceil_U16) {
const std::vector<float> input_data = GetFloatDataInRange(-12.0f, 12.0f, 6);
RunQDQOpTest<uint16_t>("Ceil",
{TestInputDef<float>({1, 2, 3}, false, input_data)},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ parameters:
- name: QnnSdk
displayName: QNN SDK version
type: string
default: qnn-v2.19.2.240210
default: 2.21.0.240401

jobs:
- job: Build_QNN_EP
Expand All @@ -40,10 +40,6 @@ jobs:
workspace:
clean: all

variables:
- name: QNN_SDK_ROOT
value: /data/qnnsdk/${{parameters.QnnSdk}}

steps:
- task: UsePythonVersion@0
displayName: Use Python $(pythonVersion)
Expand All @@ -56,6 +52,10 @@ jobs:
- script: sudo chmod go+rw /dev/kvm
displayName: Update permissions to KVM

- template: templates/jobs/download_linux_qnn_sdk.yml
parameters:
QnnSDKVersion: ${{ parameters.QnnSdk }}

- script: |
export ANDROID_SDK_ROOT=/usr/local/lib/android/sdk
export ANDROID_HOME=/usr/local/lib/android/sdk
Expand All @@ -78,7 +78,7 @@ jobs:
--android_api=31 \
--parallel \
--use_qnn \
--qnn_home $(QNN_SDK_ROOT) \
--qnn_home $(QnnSDKRootDir) \
--cmake_generator=Ninja \
--skip_tests --path_to_protoc_exe $(Build.BinariesDirectory)/installed/bin/protoc
displayName: Build QNN EP
Expand Down
23 changes: 11 additions & 12 deletions tools/ci_build/github/azure-pipelines/linux-qnn-ci-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ parameters:
- name: QnnSdk
displayName: QNN SDK version
type: string
default: qnn-v2.19.2.240210
default: 2.21.0.240401

jobs:
- job: Build_QNN_EP
Expand All @@ -41,13 +41,8 @@ jobs:
workspace:
clean: all

variables:
- name: QNN_SDK_ROOT
value: /data/qnnsdk/${{parameters.QnnSdk}}

steps:
- script: |
ls /data/qnnsdk
ls -R /data/qnn_test_data
displayName: Check QNN test data
Expand All @@ -59,13 +54,17 @@ jobs:
- script: sudo apt-get update -y && sudo apt-get install -y coreutils ninja-build
displayName: Install coreutils and ninja

- template: templates/jobs/download_linux_qnn_sdk.yml
parameters:
QnnSDKVersion: ${{ parameters.QnnSdk }}

- script: |
python3 tools/ci_build/build.py \
--build_dir build \
--config Release \
--parallel --use_binskim_compliant_compile_flags \
--use_qnn \
--qnn_home $(QNN_SDK_ROOT) \
--qnn_home $(QnnSDKRootDir) \
--cmake_generator=Ninja \
--skip_tests
displayName: Build QNN EP
Expand All @@ -75,7 +74,7 @@ jobs:
--build_dir build \
--config Release --use_binskim_compliant_compile_flags \
--test \
--qnn_home $(QNN_SDK_ROOT) \
--qnn_home $(QnnSDKRootDir) \
--cmake_generator=Ninja \
--skip_submodule_sync \
--ctest_path ""
Expand All @@ -86,29 +85,29 @@ jobs:
inputs:
script: |
./build/Release/onnx_test_runner -e qnn \
-v -j 1 -i "backend_path|$(QNN_SDK_ROOT)/lib/x86_64-linux-clang/libQnnCpu.so" \
-v -j 1 -i "backend_path|$(QnnSDKRootDir)/lib/x86_64-linux-clang/libQnnCpu.so" \
cmake/external/onnx/onnx/backend/test/data/node
- task: CmdLine@2
displayName: Run float32 model tests
inputs:
script: |
./build/Release/onnx_test_runner -e qnn \
-v -j 1 -i "backend_path|$(QNN_SDK_ROOT)/lib/x86_64-linux-clang/libQnnCpu.so" \
-v -j 1 -i "backend_path|$(QnnSDKRootDir)/lib/x86_64-linux-clang/libQnnCpu.so" \
/data/float32_models
- task: CmdLine@2
displayName: Run QDQ model tests
inputs:
script: |
./build/Release/onnx_test_runner -e qnn \
-v -j 1 -i "backend_path|$(QNN_SDK_ROOT)/lib/x86_64-linux-clang/libQnnHtp.so" \
-v -j 1 -i "backend_path|$(QnnSDKRootDir)/lib/x86_64-linux-clang/libQnnHtp.so" \
/data/qdq_models
- task: CmdLine@2
displayName: Run QDQ model tests with context cache enabled
inputs:
script: |
./build/Release/onnx_test_runner -e qnn \
-v -f -j 1 -i "backend_path|$(QNN_SDK_ROOT)/lib/x86_64-linux-clang/libQnnHtp.so" \
-v -f -j 1 -i "backend_path|$(QnnSDKRootDir)/lib/x86_64-linux-clang/libQnnHtp.so" \
/data/qdq_models/mobilenetv2-1.0_add_transpose_quant
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ parameters:
- name: qnn_sdk_version
type: string
displayName: 'QNN SDK version. Only for QNN packages.'
default: 2.19.2.240210
default: 2.21.0.240401

trigger: none

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ parameters:
- name: QnnSdk
displayName: QNN SDK Version
type: string
default: 2.19.2.240210
default: 2.21.0.240401

- name: build_config
displayName: Build Configuration
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
parameters:
- name: QnnSDKVersion
type: string
default: '2.21.0.240401'

steps:
- script: |
azcopy cp --recursive https://lotusscus.blob.core.windows.net/models/qnnsdk/qnn-v${{ parameters.QnnSDKVersion }} $(Agent.TempDirectory)
displayName: 'Download QNN SDK v${{ parameters.QnnSDKVersion }}'
- bash: |
echo "##vso[task.setvariable variable=QnnSDKRootDir]$(Agent.TempDirectory)/qnn-v${{ parameters.QnnSDKVersion }}"
displayName: Set QnnSDKRootDir
- script: |
echo $(QnnSDKRootDir)
displayName: 'Print QnnSDKRootDir after downloading QNN SDK'
- script: |
azcopy cp --recursive 'https://lotusscus.blob.core.windows.net/models/qnnsdk/Qualcomm AI Hub Proprietary License.pdf' $(QnnSDKRootDir)
displayName: 'Download Qualcomm AI Hub license'
- script: |
ls -al $(QnnSDKRootDir)
displayName: 'Print contents of QNN SDK'
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
parameters:
- name: QnnSDKVersion
type: string
default: '2.19.2.240210'
default: '2.21.0.240401'

steps:
- powershell: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ parameters:
- name: qnn_sdk_version
type: string
displayName: 'QNN SDK version. Only for QNN packages.'
default: 2.19.2.240210
default: 2.21.0.240401

stages:
- ${{ if eq(parameters.enable_windows_cpu, true) }}:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ parameters:
- name: QNN_SDK
displayName: QNN SDK Version
type: string
default: 2.19.2.240210
default: 2.21.0.240401

- name: PYTHON_VERSION
type: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ parameters:
- name: QNN_SDK
displayName: QNN SDK Version
type: string
default: 2.19.2.240210
default: 2.21.0.240401

- name: ENV_SETUP_SCRIPT
type: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ parameters:
- name: QnnSdk
displayName: QNN SDK version
type: string
default: qnn-v2.19.2.240210_win
default: 2.21.0.240401

jobs:
- job: 'build'
Expand All @@ -42,7 +42,6 @@ jobs:
buildArch: arm64
BuildConfig: 'RelWithDebInfo'
ALLOW_RELEASED_ONNX_OPSET_ONLY: '1'
QNN_SDK_ROOT: 'C:\data\qnnsdk\${{parameters.QnnSdk}}'
timeoutInMinutes: 240
workspace:
clean: all
Expand All @@ -57,10 +56,6 @@ jobs:
DIR $(Agent.ToolsDirectory)\Python\3.11.0\arm64
displayName: Copy python 3.11.0 version to agent tools directory
- script: |
DIR C:\data\qnnsdk
displayName: Check available QNN SDKs
- task: UsePythonVersion@0
inputs:
versionSpec: '3.x'
Expand All @@ -71,11 +66,15 @@ jobs:
inputs:
versionSpec: 6.4.x

- template: templates/jobs/download_win_qnn_sdk.yml
parameters:
QnnSDKVersion: ${{ parameters.QnnSdk }}

- task: PythonScript@0
displayName: 'Build'
inputs:
scriptPath: '$(Build.SourcesDirectory)\tools\ci_build\build.py'
arguments: '--config $(BuildConfig) --build_dir $(Build.BinariesDirectory) --skip_tests --cmake_generator "Visual Studio 17 2022" --use_qnn --qnn_home $(QNN_SDK_ROOT) --parallel'
arguments: '--config $(BuildConfig) --build_dir $(Build.BinariesDirectory) --skip_tests --cmake_generator "Visual Studio 17 2022" --use_qnn --qnn_home $(QnnSDKRootDir) --parallel'
workingDirectory: '$(Build.BinariesDirectory)'

- powershell: |
Expand All @@ -84,17 +83,17 @@ jobs:
displayName: 'Run unit tests'
- script: |
.\$(BuildConfig)\onnx_test_runner -j 1 -v -e qnn -i "backend_path|$(QNN_SDK_ROOT)\lib\aarch64-windows-msvc\QnnCpu.dll" $(Build.SourcesDirectory)\cmake\external\onnx\onnx\backend\test\data\node
.\$(BuildConfig)\onnx_test_runner -j 1 -v -e qnn -i "backend_path|$(QnnSDKRootDir)\lib\aarch64-windows-msvc\QnnCpu.dll" $(Build.SourcesDirectory)\cmake\external\onnx\onnx\backend\test\data\node
workingDirectory: '$(Build.BinariesDirectory)\$(BuildConfig)'
displayName: 'Run ONNX Tests'
- script: |
.\$(BuildConfig)\onnx_test_runner -j 1 -v -e qnn -i "backend_path|$(QNN_SDK_ROOT)\lib\aarch64-windows-msvc\QnnCpu.dll" C:\data\float32_models
.\$(BuildConfig)\onnx_test_runner -j 1 -v -e qnn -i "backend_path|$(QnnSDKRootDir)\lib\aarch64-windows-msvc\QnnCpu.dll" C:\data\float32_models
workingDirectory: '$(Build.BinariesDirectory)\$(BuildConfig)'
displayName: 'Run float32 model tests'
- script: |
.\$(BuildConfig)\onnx_test_runner -j 1 -v -e qnn -i "backend_path|$(QNN_SDK_ROOT)\lib\aarch64-windows-msvc\QnnHtp.dll" C:\data\qdq_models
.\$(BuildConfig)\onnx_test_runner -j 1 -v -e qnn -i "backend_path|$(QnnSDKRootDir)\lib\aarch64-windows-msvc\QnnHtp.dll" C:\data\qdq_models
workingDirectory: '$(Build.BinariesDirectory)\$(BuildConfig)'
displayName: 'Run QDQ model tests'
enabled: false
Expand Down
Loading

0 comments on commit 0dda8b0

Please sign in to comment.