diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 3d4f055bb6..246675b72f 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -838,7 +838,10 @@ if (onnxruntime_USE_QNN) endif() if (MSVC OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - file(GLOB QNN_LIB_FILES LIST_DIRECTORIES false "${onnxruntime_QNN_HOME}/lib/${QNN_ARCH_ABI}/libQnn*.so" "${onnxruntime_QNN_HOME}/lib/${QNN_ARCH_ABI}/Qnn*.dll") + file(GLOB QNN_LIB_FILES LIST_DIRECTORIES false "${onnxruntime_QNN_HOME}/lib/${QNN_ARCH_ABI}/libQnn*.so" + "${onnxruntime_QNN_HOME}/lib/${QNN_ARCH_ABI}/Qnn*.dll" + "${onnxruntime_QNN_HOME}/lib/${QNN_ARCH_ABI}/libHtpPrepare.so" + "${onnxruntime_QNN_HOME}/lib/${QNN_ARCH_ABI}/HtpPrepare.dll") if (${QNN_ARCH_ABI} STREQUAL "aarch64-windows-msvc" OR ${QNN_ARCH_ABI} STREQUAL "arm64x-windows-msvc") file(GLOB EXTRA_HTP_LIB LIST_DIRECTORIES false "${onnxruntime_QNN_HOME}/lib/hexagon-v68/unsigned/libQnnHtpV68Skel.so" "${onnxruntime_QNN_HOME}/lib/hexagon-v73/unsigned/libQnnHtpV73Skel.so" diff --git a/cmake/onnxruntime_python.cmake b/cmake/onnxruntime_python.cmake index 7c8aae1bce..3a87a78d2b 100644 --- a/cmake/onnxruntime_python.cmake +++ b/cmake/onnxruntime_python.cmake @@ -1034,6 +1034,12 @@ if (onnxruntime_USE_QNN) ${QNN_LIB_FILES} $/onnxruntime/capi/ ) + add_custom_command( + TARGET onnxruntime_pybind11_state POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + $ + $/onnxruntime/capi/ + ) if (EXISTS "${onnxruntime_QNN_HOME}/Qualcomm AI Hub Proprietary License.pdf") add_custom_command( TARGET onnxruntime_pybind11_state POST_BUILD diff --git a/setup.py b/setup.py index f471e9cd0e..950445a8fb 100644 --- a/setup.py +++ b/setup.py @@ -59,6 +59,7 @@ rocm_version = None is_migraphx = False is_rocm = False is_openvino = False +is_qnn = False # The following arguments are mutually exclusive if wheel_name_suffix == "gpu": # TODO: how to support multiple CUDA versions? @@ -87,7 +88,8 @@ elif parse_arg_remove_boolean(sys.argv, "--use_azure"): # keep the same name since AzureEP will release with CpuEP by default. pass elif parse_arg_remove_boolean(sys.argv, "--use_qnn"): - package_name = "onnxruntime-qnn" + is_qnn = True + package_name = "onnxruntime-qnn" if not nightly_build else "ort-qnn-nightly" if is_rocm or is_migraphx: package_name = "onnxruntime-rocm" if not nightly_build else "ort-rocm-nightly" @@ -278,7 +280,7 @@ try: pass _bdist_wheel.run(self) - if is_manylinux and not disable_auditwheel_repair and not is_openvino: + if is_manylinux and not disable_auditwheel_repair and not is_openvino and not is_qnn: assert self.dist_dir is not None file = glob(path.join(self.dist_dir, "*linux*.whl"))[0] logger.info("repairing %s for manylinux1", file) @@ -348,6 +350,16 @@ if platform.system() == "Linux" or platform.system() == "AIX": libs.append(providers_cuda_or_rocm) libs.append(providers_tensorrt_or_migraphx) libs.append(providers_cann) + # QNN + qnn_deps = [ + "libQnnCpu.so", + "libQnnHtp.so", + "libQnnSaver.so", + "libQnnSystem.so", + "libHtpPrepare.so", + "onnxruntime_qnn_ctx_gen", + ] + dl_libs.extend(qnn_deps) if nightly_build: libs.extend(["libonnxruntime_pywrapper.so"]) elif platform.system() == "Darwin": diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index 8535f1e8c8..8c24517784 100644 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -2277,10 +2277,10 @@ def build_python_wheel( args.append("--wheel_name_suffix=directml") elif use_cann: args.append("--use_cann") - elif use_azure: - args.append("--use_azure") elif use_qnn: args.append("--use_qnn") + elif use_azure: + args.append("--use_azure") run_subprocess(args, cwd=cwd) diff --git a/tools/ci_build/github/azure-pipelines/orttraining-py-packaging-pipeline-cpu.yml b/tools/ci_build/github/azure-pipelines/orttraining-py-packaging-pipeline-cpu.yml index 5ecb35aa25..a71e10f95f 100644 --- a/tools/ci_build/github/azure-pipelines/orttraining-py-packaging-pipeline-cpu.yml +++ b/tools/ci_build/github/azure-pipelines/orttraining-py-packaging-pipeline-cpu.yml @@ -25,3 +25,4 @@ stages: enable_windows_arm64_qnn: false enable_windows_arm64ec_qnn: false enable_windows_x64_qnn: false + enable_linux_x64_qnn: false diff --git a/tools/ci_build/github/azure-pipelines/py-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/py-packaging-pipeline.yml index 8107c1a890..7263239c6c 100644 --- a/tools/ci_build/github/azure-pipelines/py-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/py-packaging-pipeline.yml @@ -44,6 +44,11 @@ parameters: type: boolean default: true +- name: enable_linux_x64_qnn + displayName: 'Whether Linux x86_64 package with QNN EP is built.' + type: boolean + default: true + - name: build_py_parameters displayName: 'Specify extra build parameters' type: string @@ -80,6 +85,7 @@ stages: enable_windows_arm64_qnn: ${{ parameters.enable_windows_arm64_qnn }} enable_windows_arm64ec_qnn: ${{ parameters.enable_windows_arm64ec_qnn }} enable_windows_x64_qnn: ${{ parameters.enable_windows_x64_qnn }} + enable_linux_x64_qnn: ${{ parameters.enable_linux_x64_qnn }} build_py_parameters: ${{ parameters.build_py_parameters }} cmake_build_type: ${{ parameters.cmake_build_type }} qnn_sdk_version: ${{ parameters.qnn_sdk_version }} diff --git a/tools/ci_build/github/azure-pipelines/templates/py-linux-qnn.yml b/tools/ci_build/github/azure-pipelines/templates/py-linux-qnn.yml new file mode 100644 index 0000000000..6220a9a46c --- /dev/null +++ b/tools/ci_build/github/azure-pipelines/templates/py-linux-qnn.yml @@ -0,0 +1,97 @@ +parameters: +- name: machine_pool + type: string + +- name: cmake_build_type + type: string + default: 'Release' + values: + - Debug + - Release + - RelWithDebInfo + - MinSizeRel + +- name: device + type: string + default: 'NPU' + +- name: with_cache + type: boolean + default: false + +- name: extra_build_arg + type: string + default: '' + +- name: QnnSdk + displayName: QNN SDK version + type: string + default: 2.26.0.240828 + +jobs: +- job: Linux_py_qnn_Wheels_x64 + timeoutInMinutes: 240 + workspace: + clean: all + pool: ${{ parameters.machine_pool }} + variables: + # The build machine pool doesn't have dotnet, so it can't run CG. + - name: skipComponentGovernanceDetection + value: true + - name: ORT_CACHE_DIR + value: $(Agent.TempDirectory)/ort_ccache + - name: TODAY + value: $[format('{0:dd}{0:MM}{0:yyyy}', pipeline.startTime)] + - name: extra_build_args + ${{ if ne(parameters.extra_build_arg, '') }}: + value: -x ${{ parameters.extra_build_arg }} + ${{ if eq(parameters.extra_build_arg, '') }}: + value: '' + steps: + - task: mspremier.PostBuildCleanup.PostBuildCleanup-task.PostBuildCleanup@3 + displayName: 'Clean Agent Directories' + condition: always() + + - checkout: self + clean: true + submodules: none + + - template: jobs/download_linux_qnn_sdk.yml + parameters: + QnnSDKVersion: ${{ parameters.QnnSdk }} + + - template: set-nightly-build-option-variable-step.yml + + - template: get-docker-image-steps.yml + parameters: + Dockerfile: tools/ci_build/github/linux/docker/inference/x86_64/python/cpu/Dockerfile + Context: tools/ci_build/github/linux/docker/inference/x86_64/python/cpu + DockerBuildArgs: "--build-arg BUILD_UID=$( id -u )" + Repository: onnxruntimecpubuildpythonx86_64_qnn + + - template: linux-build-step-with-cache.yml + parameters: + WithCache: ${{parameters.with_cache}} + Today: $(TODAY) + AdditionalKey: Linux_py_qnn_Wheels_x64 + CacheDir: $(ORT_CACHE_DIR) + ChangeEveryCommit: true + BuildStep: + - task: Bash@3 + displayName: 'Build Python Wheel' + inputs: + targetType: filePath + filePath: tools/ci_build/github/linux/run_python_dockerbuild.sh + arguments: -i onnxruntimecpubuildpythonx86_64_qnn -d "${{ parameters.device }}" -c ${{ parameters.cmake_build_type }} $(extra_build_args) + env: + ADDITIONAL_DOCKER_PARAMETER: "--volume $(QnnSDKRootDir):/qnn_sdk" + + - task: PublishBuildArtifacts@1 + displayName: 'Publish Artifact: Linux ONNXRuntime QNN python wheel' + inputs: + PathtoPublish: '$(Build.BinariesDirectory)/dist' + ArtifactName: onnxruntime-linux-qnn-x64 + + - template: component-governance-component-detection-steps.yml + parameters : + condition : 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/templates/py-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/templates/py-packaging-stage.yml index 504aed9ff3..5c5ccdef98 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-packaging-stage.yml @@ -50,6 +50,11 @@ parameters: type: boolean default: true +- name: enable_linux_x64_qnn + displayName: 'Whether Linux x86_64 package with QNN EP is built.' + type: boolean + default: true + - name: cmake_build_type type: string displayName: 'Linux packages cmake build type. Linux Only.' @@ -533,3 +538,13 @@ stages: MACHINE_POOL: 'Onnxruntime-QNNEP-Windows-2022-CPU' QNN_SDK: ${{ parameters.qnn_sdk_version }} BUILD_PY_PARAMETERS: ${{ parameters.build_py_parameters }} + + - ${{ if eq(parameters.enable_linux_x64_qnn, true) }}: + - stage: Python_Packaging_Linux_x64_QNN + dependsOn: [] + jobs: + - template: py-linux-qnn.yml + parameters: + machine_pool: 'onnxruntime-Ubuntu2204-AMD-CPU' + extra_build_arg: ${{ parameters.build_py_parameters }} + cmake_build_type: ${{ parameters.cmake_build_type }} diff --git a/tools/ci_build/github/linux/build_linux_python_package.sh b/tools/ci_build/github/linux/build_linux_python_package.sh index e7909fa4ff..ccc201cbc8 100755 --- a/tools/ci_build/github/linux/build_linux_python_package.sh +++ b/tools/ci_build/github/linux/build_linux_python_package.sh @@ -13,12 +13,12 @@ PYTHON_EXES=("/opt/python/cp38-cp38/bin/python3.8" "/opt/python/cp39-cp39/bin/py while getopts "d:p:x:c:" parameter_Option do case "${parameter_Option}" in -#GPU or CPU. +#GPU|CPU|NPU. d) BUILD_DEVICE=${OPTARG};; p) PYTHON_EXES=${OPTARG};; x) EXTRA_ARG=${OPTARG};; c) BUILD_CONFIG=${OPTARG};; -*) echo "Usage: $0 -d [-p ] [-x ] [-c ]" +*) echo "Usage: $0 -d [-p ] [-x ] [-c ]" exit 1;; esac done @@ -55,6 +55,11 @@ if [ "$BUILD_DEVICE" == "GPU" ]; then BUILD_ARGS+=("--nvcc_threads=1" "--use_cuda" "--use_tensorrt" "--cuda_version=$SHORT_CUDA_VERSION" "--tensorrt_home=/usr" "--cuda_home=/usr/local/cuda-$SHORT_CUDA_VERSION" "--cudnn_home=/usr/local/cuda-$SHORT_CUDA_VERSION" "--cmake_extra_defines" "CMAKE_CUDA_ARCHITECTURES=52;60;61;70;75;80") fi +if [ "$BUILD_DEVICE" == "NPU" ]; then + #Enable QNN EP + BUILD_ARGS+=("--use_qnn" "--qnn_home=/qnn_sdk") +fi + for PYTHON_EXE in "${PYTHON_EXES[@]}" do rm -rf /build/"$BUILD_CONFIG"