From 88c811b6382cec6cce5edb83f61f1ce7fbd987ec Mon Sep 17 00:00:00 2001 From: vraspar Date: Sun, 4 Aug 2024 12:47:16 -0700 Subject: [PATCH 01/15] Restructure MacOS framework package to fix malformed Framework errors (#21536) ### Description Refactor framework directory structure for MacOS packages ### Motivation and Context Apple started enforcing specific [framework structure](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html) for MacOS packages. We need to change how we package for MacOS to follow the guidelines Fixes following issue: [Malformed Framework](https://github.com/microsoft/onnxruntime-swift-package-manager/issues/19 ) --- .../assemble_apple_packaging_artifacts.sh | 28 ++++++++- .../github/apple/build_apple_framework.py | 58 +++++++++++++++---- 2 files changed, 73 insertions(+), 13 deletions(-) diff --git a/tools/ci_build/github/apple/assemble_apple_packaging_artifacts.sh b/tools/ci_build/github/apple/assemble_apple_packaging_artifacts.sh index 317048506ac67..f96227a750346 100755 --- a/tools/ci_build/github/apple/assemble_apple_packaging_artifacts.sh +++ b/tools/ci_build/github/apple/assemble_apple_packaging_artifacts.sh @@ -23,10 +23,36 @@ ORT_POD_VERSION=${4:?${USAGE_TEXT}} POD_ARCHIVE_BASENAME="pod-archive-${POD_NAME}-${ORT_POD_VERSION}.zip" PODSPEC_BASENAME="${POD_NAME}.podspec" + +# Macos requires a different structure for the framework +# This will create the necessary symlinks for the macos framework before packaging +# Adding the symlinks here rather than in the build script ensures that symlinks are not lost +for MACOS_DIR in "${BINARIES_STAGING_DIR}/${POD_NAME}/onnxruntime.xcframework/macos"*; do + if [ -d "${MACOS_DIR}" ]; then + echo "Creating symlinks for ${MACOS_DIR}" + pushd "${MACOS_DIR}/onnxruntime.framework" + + rm -rf Headers Resources onnxruntime + rm -rf Versions/Current + + ln -sfn A Versions/Current + ln -sfn Versions/Current/Headers Headers + ln -sfn Versions/Current/Resources Resources + ln -sfn Versions/Current/onnxruntime onnxruntime + + popd + + fi +done + + +echo "Contents of ${BINARIES_STAGING_DIR}/${POD_NAME}:" +ls -lR "${BINARIES_STAGING_DIR}/${POD_NAME}" + pushd "${BINARIES_STAGING_DIR}/${POD_NAME}" # assemble the files in the artifacts staging directory -zip -r "${ARTIFACTS_STAGING_DIR}/${POD_ARCHIVE_BASENAME}" ./* --exclude "${PODSPEC_BASENAME}" +zip -r -y "${ARTIFACTS_STAGING_DIR}/${POD_ARCHIVE_BASENAME}" ./* --exclude "${PODSPEC_BASENAME}" cp "${PODSPEC_BASENAME}" "${ARTIFACTS_STAGING_DIR}/${PODSPEC_BASENAME}" popd diff --git a/tools/ci_build/github/apple/build_apple_framework.py b/tools/ci_build/github/apple/build_apple_framework.py index 3cd7a3af70622..7270bdd56523c 100644 --- a/tools/ci_build/github/apple/build_apple_framework.py +++ b/tools/ci_build/github/apple/build_apple_framework.py @@ -89,18 +89,52 @@ def _build_for_apple_sysroot( pathlib.Path(framework_dir).mkdir(parents=True, exist_ok=True) # copy the Info.plist, framework_info.json, and header files - shutil.copy(info_plist_path, framework_dir) - shutil.copy(framework_info_path, os.path.dirname(framework_dir)) - header_dir = os.path.join(framework_dir, "Headers") - pathlib.Path(header_dir).mkdir(parents=True, exist_ok=True) - for _header in headers: - shutil.copy(_header, header_dir) - - # use lipo to create a fat ort library - lipo_command = ["lipo", "-create"] - lipo_command += ort_libs - lipo_command += ["-output", os.path.join(framework_dir, "onnxruntime")] - subprocess.run(lipo_command, shell=False, check=True) + + # macos requires different framework structure: + # https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html + if sysroot == "macosx" or sysroot == "macabi": + # create headers and resources directory + header_dir = os.path.join(framework_dir, "Versions", "A", "Headers") + resource_dir = os.path.join(framework_dir, "Versions", "A", "Resources") + pathlib.Path(header_dir).mkdir(parents=True, exist_ok=True) + pathlib.Path(resource_dir).mkdir(parents=True, exist_ok=True) + + shutil.copy(info_plist_path, resource_dir) + shutil.copy(framework_info_path, os.path.dirname(framework_dir)) + + for _header in headers: + shutil.copy(_header, header_dir) + + # use lipo to create a fat ort library + lipo_command = ["lipo", "-create"] + lipo_command += ort_libs + lipo_command += ["-output", os.path.join(framework_dir, "Versions", "A", "onnxruntime")] + subprocess.run(lipo_command, shell=False, check=True) + + # create the symbolic link + pathlib.Path(os.path.join(framework_dir, "Versions", "Current")).symlink_to("A", target_is_directory=True) + pathlib.Path(os.path.join(framework_dir, "Headers")).symlink_to( + "Versions/Current/Headers", target_is_directory=True + ) + pathlib.Path(os.path.join(framework_dir, "Resources")).symlink_to( + "Versions/Current/Resources", target_is_directory=True + ) + pathlib.Path(os.path.join(framework_dir, "onnxruntime")).symlink_to("Versions/Current/onnxruntime") + + else: + shutil.copy(info_plist_path, framework_dir) + shutil.copy(framework_info_path, os.path.dirname(framework_dir)) + header_dir = os.path.join(framework_dir, "Headers") + pathlib.Path(header_dir).mkdir(parents=True, exist_ok=True) + + for _header in headers: + shutil.copy(_header, header_dir) + + # use lipo to create a fat ort library + lipo_command = ["lipo", "-create"] + lipo_command += ort_libs + lipo_command += ["-output", os.path.join(framework_dir, "onnxruntime")] + subprocess.run(lipo_command, shell=False, check=True) return framework_dir From 134f47743ed4d20713f131dbccfdd692443e9252 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Mon, 5 Aug 2024 15:46:04 -0700 Subject: [PATCH 02/15] bumps up version in main from 1.19 -> 1.20 (#21588) Bump up version in main from 1.19.0 to 1.20.0 since the release branch has been cut. --- VERSION_NUMBER | 2 +- .../Training/NativeTrainingMethods.shared.cs | 2 +- docs/python/README.rst | 5 +++++ include/onnxruntime/core/session/onnxruntime_c_api.h | 2 +- js/common/lib/version.ts | 2 +- js/common/package-lock.json | 4 ++-- js/common/package.json | 2 +- js/node/lib/version.ts | 2 +- js/node/package-lock.json | 6 +++--- js/node/package.json | 2 +- js/react_native/lib/version.ts | 2 +- js/react_native/package.json | 2 +- js/react_native/yarn.lock | 2 +- js/web/lib/version.ts | 2 +- js/web/package-lock.json | 6 +++--- js/web/package.json | 2 +- onnxruntime/__init__.py | 2 +- onnxruntime/core/session/onnxruntime_c_api.cc | 8 ++++---- 18 files changed, 30 insertions(+), 25 deletions(-) diff --git a/VERSION_NUMBER b/VERSION_NUMBER index 815d5ca06d530..3989355915568 100644 --- a/VERSION_NUMBER +++ b/VERSION_NUMBER @@ -1 +1 @@ -1.19.0 +1.20.0 diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/Training/NativeTrainingMethods.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/Training/NativeTrainingMethods.shared.cs index 1ba5f14641e78..9b1df9357dc88 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/Training/NativeTrainingMethods.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/Training/NativeTrainingMethods.shared.cs @@ -76,7 +76,7 @@ static NativeTrainingMethods() DOrtGetApi OrtGetApi = (DOrtGetApi)Marshal.GetDelegateForFunctionPointer(NativeMethods.OrtGetApiBase().GetApi, typeof(DOrtGetApi)); #endif - const uint ORT_API_VERSION = 19; + const uint ORT_API_VERSION = 20; #if NETSTANDARD2_0 IntPtr ortApiPtr = OrtGetApi(ORT_API_VERSION); api_ = (OrtApi)Marshal.PtrToStructure(ortApiPtr, typeof(OrtApi)); diff --git a/docs/python/README.rst b/docs/python/README.rst index 6c493e206a493..5a45bf6cef8ed 100644 --- a/docs/python/README.rst +++ b/docs/python/README.rst @@ -8,6 +8,11 @@ For more information on ONNX Runtime, please see `aka.ms/onnxruntime `_ or the `Github project `_. """ -__version__ = "1.19.0" +__version__ = "1.20.0" __author__ = "Microsoft" # we need to do device version validation (for example to check Cuda version for an onnxruntime-training package). diff --git a/onnxruntime/core/session/onnxruntime_c_api.cc b/onnxruntime/core/session/onnxruntime_c_api.cc index 5cf5ff9b3bd0a..1a5484ddc0055 100644 --- a/onnxruntime/core/session/onnxruntime_c_api.cc +++ b/onnxruntime/core/session/onnxruntime_c_api.cc @@ -2396,7 +2396,7 @@ Second example, if we wanted to add and remove some members, we'd do this: In GetApi we now make it return ort_api_3 for version 3. */ -static constexpr OrtApi ort_api_1_to_19 = { +static constexpr OrtApi ort_api_1_to_20 = { // NOTE: The ordering of these fields MUST not change after that version has shipped since existing binaries depend on this ordering. // Shipped as version 1 - DO NOT MODIFY (see above text for more information) @@ -2763,16 +2763,16 @@ static_assert(offsetof(OrtApi, SessionOptionsAppendExecutionProvider_OpenVINO_V2 static_assert(offsetof(OrtApi, AddExternalInitializersFromFilesInMemory) / sizeof(void*) == 279, "Size of version 18 API cannot change"); // So that nobody forgets to finish an API version, this check will serve as a reminder: -static_assert(std::string_view(ORT_VERSION) == "1.19.0", +static_assert(std::string_view(ORT_VERSION) == "1.20.0", "ORT_Version change detected, please follow below steps to ensure OrtApi is updated properly"); // 1. Update the hardcoded version string in above static_assert to silence it -// 2. If there were any APIs added to ort_api_1_to_19 above: +// 2. If there were any APIs added to ort_api_1_to_20 above: // a. Add the 'End of version #' markers (pattern above should be obvious) // b. Add a static_assert in the directly above list of version sizes to ensure nobody adds any more functions to the just shipped API version ORT_API(const OrtApi*, OrtApis::GetApi, uint32_t version) { if (version >= 1 && version <= ORT_API_VERSION) - return &ort_api_1_to_19; + return &ort_api_1_to_20; fprintf(stderr, "The requested API version [%u] is not available, only API versions [1, %u] are supported in this build." From bcc01ac1230adaa0dfcb1e2ace037e627b67d42e Mon Sep 17 00:00:00 2001 From: Scott McKay Date: Tue, 6 Aug 2024 08:50:56 +1000 Subject: [PATCH 03/15] Updates to apple packaging (#21611) ### Description Add ability to test packaging without rebuilding every time. Add ability to comment out some platforms/architectures without the scripts to assemble the c/obj-c packages breaking. Update a couple of commands to preserve symlinks. ### Motivation and Context Make debugging packaging issues faster. Creates correct package for mac-catalyst and doesn't require setting symlinks via bash script. --- .../assemble_apple_packaging_artifacts.sh | 23 ----------- .../apple/build_and_assemble_apple_pods.py | 11 +++++- .../github/apple/build_apple_framework.py | 2 +- .../github/apple/c/assemble_c_pod_package.py | 13 ++++--- .../objectivec/assemble_objc_pod_package.py | 7 +++- .../github/apple/package_assembly_utils.py | 38 +++++++++++++++++++ .../github/apple/test_apple_packages.py | 5 ++- .../azure-pipelines/templates/c-api-cpu.yml | 2 +- 8 files changed, 65 insertions(+), 36 deletions(-) diff --git a/tools/ci_build/github/apple/assemble_apple_packaging_artifacts.sh b/tools/ci_build/github/apple/assemble_apple_packaging_artifacts.sh index f96227a750346..a2178337e6876 100755 --- a/tools/ci_build/github/apple/assemble_apple_packaging_artifacts.sh +++ b/tools/ci_build/github/apple/assemble_apple_packaging_artifacts.sh @@ -23,29 +23,6 @@ ORT_POD_VERSION=${4:?${USAGE_TEXT}} POD_ARCHIVE_BASENAME="pod-archive-${POD_NAME}-${ORT_POD_VERSION}.zip" PODSPEC_BASENAME="${POD_NAME}.podspec" - -# Macos requires a different structure for the framework -# This will create the necessary symlinks for the macos framework before packaging -# Adding the symlinks here rather than in the build script ensures that symlinks are not lost -for MACOS_DIR in "${BINARIES_STAGING_DIR}/${POD_NAME}/onnxruntime.xcframework/macos"*; do - if [ -d "${MACOS_DIR}" ]; then - echo "Creating symlinks for ${MACOS_DIR}" - pushd "${MACOS_DIR}/onnxruntime.framework" - - rm -rf Headers Resources onnxruntime - rm -rf Versions/Current - - ln -sfn A Versions/Current - ln -sfn Versions/Current/Headers Headers - ln -sfn Versions/Current/Resources Resources - ln -sfn Versions/Current/onnxruntime onnxruntime - - popd - - fi -done - - echo "Contents of ${BINARIES_STAGING_DIR}/${POD_NAME}:" ls -lR "${BINARIES_STAGING_DIR}/${POD_NAME}" diff --git a/tools/ci_build/github/apple/build_and_assemble_apple_pods.py b/tools/ci_build/github/apple/build_and_assemble_apple_pods.py index 5014ba11d983d..71aeb9e7b0304 100755 --- a/tools/ci_build/github/apple/build_and_assemble_apple_pods.py +++ b/tools/ci_build/github/apple/build_and_assemble_apple_pods.py @@ -57,6 +57,11 @@ def parse_args(): ) parser.add_argument("--test", action="store_true", help="Run tests on the framework and pod package files.") + parser.add_argument( + "--skip-build", + action="store_true", + help="Use build from previous run. Useful to debug test issues or packaging changes.", + ) build_framework_group = parser.add_argument_group( title="iOS framework build arguments", @@ -114,7 +119,8 @@ def main(): build_apple_framework_args += ["--build_dir", str(build_dir), args.build_settings_file] - run(build_apple_framework_args) + if not args.skip_build: + run(build_apple_framework_args) if args.test: test_apple_packages_args = [ @@ -171,7 +177,8 @@ def main(): def move_dir(src, dst): if dst.is_dir(): shutil.rmtree(dst) - shutil.move(src, dst) + shutil.copytree(src, dst, symlinks=True) + shutil.rmtree(src) move_dir(c_pod_staging_dir, staging_dir / c_pod_name) move_dir(objc_pod_staging_dir, staging_dir / objc_pod_name) diff --git a/tools/ci_build/github/apple/build_apple_framework.py b/tools/ci_build/github/apple/build_apple_framework.py index 7270bdd56523c..5a3b242c2a389 100644 --- a/tools/ci_build/github/apple/build_apple_framework.py +++ b/tools/ci_build/github/apple/build_apple_framework.py @@ -200,7 +200,7 @@ def _build_package(args): xcframework_dir = os.path.join(build_dir, "framework_out") pathlib.Path(xcframework_dir).mkdir(parents=True, exist_ok=True) shutil.copy(os.path.join(REPO_DIR, "LICENSE"), xcframework_dir) - shutil.copytree(public_headers_path, os.path.join(xcframework_dir, "Headers"), dirs_exist_ok=True) + shutil.copytree(public_headers_path, os.path.join(xcframework_dir, "Headers"), dirs_exist_ok=True, symlinks=True) _merge_framework_info_files(framework_info_files_to_merge, os.path.join(build_dir, "xcframework_info.json")) # remove existing xcframework if any diff --git a/tools/ci_build/github/apple/c/assemble_c_pod_package.py b/tools/ci_build/github/apple/c/assemble_c_pod_package.py index ca4f01cf65bd9..59052734ddd26 100644 --- a/tools/ci_build/github/apple/c/assemble_c_pod_package.py +++ b/tools/ci_build/github/apple/c/assemble_c_pod_package.py @@ -16,6 +16,7 @@ PackageVariant, copy_repo_relative_to_dir, gen_file_from_template, + get_podspec_values, load_json_config, ) @@ -66,23 +67,25 @@ def assemble_c_pod_package( print("Warning: staging directory already exists", file=sys.stderr) # copy the necessary files to the staging directory - shutil.copytree(framework_dir, staging_dir / framework_dir.name, dirs_exist_ok=True) - shutil.copytree(public_headers_dir, staging_dir / public_headers_dir.name, dirs_exist_ok=True) + shutil.copytree(framework_dir, staging_dir / framework_dir.name, dirs_exist_ok=True, symlinks=True) + shutil.copytree(public_headers_dir, staging_dir / public_headers_dir.name, dirs_exist_ok=True, symlinks=True) copy_repo_relative_to_dir(["LICENSE"], staging_dir) + (ios_deployment_target, macos_deployment_target, weak_framework) = get_podspec_values(framework_info) + # generate the podspec file from the template variable_substitutions = { "DESCRIPTION": pod_config["description"], # By default, we build both "iphoneos" and "iphonesimulator" architectures, and the deployment target should be the same between these two. - "IOS_DEPLOYMENT_TARGET": framework_info["iphonesimulator"]["APPLE_DEPLOYMENT_TARGET"], - "MACOSX_DEPLOYMENT_TARGET": framework_info.get("macosx", {}).get("APPLE_DEPLOYMENT_TARGET", ""), + "IOS_DEPLOYMENT_TARGET": ios_deployment_target, + "MACOSX_DEPLOYMENT_TARGET": macos_deployment_target, "LICENSE_FILE": "LICENSE", "NAME": pod_name, "ORT_C_FRAMEWORK": framework_dir.name, "ORT_C_HEADERS_DIR": public_headers_dir.name, "SUMMARY": pod_config["summary"], "VERSION": pod_version, - "WEAK_FRAMEWORK": framework_info["iphonesimulator"]["WEAK_FRAMEWORK"], + "WEAK_FRAMEWORK": weak_framework, } podspec_template = _script_dir / "c.podspec.template" diff --git a/tools/ci_build/github/apple/objectivec/assemble_objc_pod_package.py b/tools/ci_build/github/apple/objectivec/assemble_objc_pod_package.py index 1e26482440eae..b7eb34cb09219 100755 --- a/tools/ci_build/github/apple/objectivec/assemble_objc_pod_package.py +++ b/tools/ci_build/github/apple/objectivec/assemble_objc_pod_package.py @@ -17,6 +17,7 @@ copy_repo_relative_to_dir, filter_files, gen_file_from_template, + get_podspec_values, load_json_config, ) @@ -147,12 +148,14 @@ def assemble_objc_pod_package( def path_patterns_as_variable_value(patterns: list[str]): return ", ".join([f'"{pattern}"' for pattern in patterns]) + (ios_deployment_target, macos_deployment_target, _) = get_podspec_values(framework_info) + variable_substitutions = { "C_POD_NAME": c_pod_config["name"], "DESCRIPTION": pod_config["description"], "INCLUDE_DIR_LIST": path_patterns_as_variable_value(include_dirs), - "IOS_DEPLOYMENT_TARGET": framework_info["iphonesimulator"]["APPLE_DEPLOYMENT_TARGET"], - "MACOSX_DEPLOYMENT_TARGET": framework_info.get("macosx", {}).get("APPLE_DEPLOYMENT_TARGET", ""), + "IOS_DEPLOYMENT_TARGET": ios_deployment_target, + "MACOSX_DEPLOYMENT_TARGET": macos_deployment_target, "LICENSE_FILE": license_file, "NAME": pod_name, "PUBLIC_HEADER_FILE_LIST": path_patterns_as_variable_value(pod_files["public_header_files"]), diff --git a/tools/ci_build/github/apple/package_assembly_utils.py b/tools/ci_build/github/apple/package_assembly_utils.py index 8ab8ccdb3f966..c6822466d73d0 100644 --- a/tools/ci_build/github/apple/package_assembly_utils.py +++ b/tools/ci_build/github/apple/package_assembly_utils.py @@ -118,6 +118,44 @@ def load_json_config(json_config_file: pathlib.Path): return json.load(config) +def get_podspec_values(framework_info): + """ + Get the podspec deployement targets and weak framework info from the dictionary that load_json_config returned. + Looks for iphonesimulator, iphoneos and macos settings. + Handles missing platforms and checks consistency. + Returns empty string for deployment target if that platofrm is not enabled. + + :return (ios_deployment_target, macos_deployment_target, weak_framework) + """ + ios_deployment_target = "" + macos_deployment_target = "" + weak_framework = "" # should be the same for all platforms + # get info, allowing for a subset of platforms to be specified + for framework in ("iphonesimulator", "iphoneos", "macosx"): + if framework not in framework_info: + continue + + target = framework_info[framework]["APPLE_DEPLOYMENT_TARGET"] + weak = framework_info[framework]["WEAK_FRAMEWORK"] + + if not weak_framework: + weak_framework = weak + else: + # should be consistent + assert weak == weak_framework + + if framework == "macosx": + macos_deployment_target = target + else: + if not ios_deployment_target: + ios_deployment_target = target + else: + # should be consistent + assert ios_deployment_target == target + + return (ios_deployment_target, macos_deployment_target, weak_framework) + + def get_ort_version(): """ Gets the ONNX Runtime version string from the repo. diff --git a/tools/ci_build/github/apple/test_apple_packages.py b/tools/ci_build/github/apple/test_apple_packages.py index 8f06d6dd68fbc..14c0b46676ac6 100644 --- a/tools/ci_build/github/apple/test_apple_packages.py +++ b/tools/ci_build/github/apple/test_apple_packages.py @@ -89,8 +89,9 @@ def _test_apple_packages(args): # create a zip file contains the framework zip_file_path = local_pods_dir / f"{pod_name}.zip" - # shutil.make_archive require target file as full path without extension - shutil.make_archive(zip_file_path.with_suffix(""), "zip", root_dir=local_pods_dir) + + # shutil.make_archive doesn't preserve symlinks. we know this is running on macOS so use zip + subprocess.run(["zip", "-r", "-y", str(zip_file_path), "."], cwd=local_pods_dir, check=True) # update the podspec to point to the local framework zip file with open(podspec) as file: diff --git a/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml b/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml index ec97da3786fd9..0368c91290d5e 100644 --- a/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml +++ b/tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml @@ -111,7 +111,7 @@ stages: cp -R $(Build.BinariesDirectory)/ios_framework/framework_out/onnxruntime.xcframework \ $(Build.BinariesDirectory)/artifacts_staging/onnxruntime-ios-xcframework-$(OnnxRuntimeVersion) pushd $(Build.BinariesDirectory)/artifacts_staging - zip -vr $(Build.BinariesDirectory)/artifacts/onnxruntime_xcframework.zip \ + zip -vry $(Build.BinariesDirectory)/artifacts/onnxruntime_xcframework.zip \ onnxruntime-ios-xcframework-$(OnnxRuntimeVersion) popd displayName: "Build Apple xcframework" From a5ce65d87ae0ec18190ebb6ef5ec4170afb187f4 Mon Sep 17 00:00:00 2001 From: Edward Chen <18449977+edgchen1@users.noreply.github.com> Date: Mon, 5 Aug 2024 16:38:20 -0700 Subject: [PATCH 04/15] Clean up some mobile package related files and their usages. (#21606) The mobile packages have been removed. --- cmake/onnxruntime_python.cmake | 1 - docs/ORTMobilePackageOperatorTypeSupport.md | 132 -------- .../mobile_package.required_operators.config | 46 --- ...bile_package.required_operators.readme.txt | 82 ----- .../binary-size-checks-pipeline.yml | 12 - ...oid_minimal_with_mobile_package_ops.config | 19 -- tools/python/gen_ort_mobile_pkg_doc.py | 97 ------ .../check_model_can_use_ort_mobile_pkg.py | 301 ------------------ 8 files changed, 690 deletions(-) delete mode 100644 docs/ORTMobilePackageOperatorTypeSupport.md delete mode 100644 tools/ci_build/github/android/mobile_package.required_operators.config delete mode 100644 tools/ci_build/github/android/mobile_package.required_operators.readme.txt delete mode 100644 tools/ci_build/github/linux/ort_minimal/build_check_binsize_config/android_minimal_with_mobile_package_ops.config delete mode 100644 tools/python/gen_ort_mobile_pkg_doc.py delete mode 100644 tools/python/util/mobile_helpers/check_model_can_use_ort_mobile_pkg.py diff --git a/cmake/onnxruntime_python.cmake b/cmake/onnxruntime_python.cmake index 372db15b108fb..b2dbe4b3da5e8 100644 --- a/cmake/onnxruntime_python.cmake +++ b/cmake/onnxruntime_python.cmake @@ -508,7 +508,6 @@ file(GLOB onnxruntime_ort_format_model_srcs CONFIGURE_DEPENDS ) file(GLOB onnxruntime_mobile_helpers_srcs CONFIGURE_DEPENDS ${REPO_ROOT}/tools/python/util/mobile_helpers/*.py - ${REPO_ROOT}/tools/ci_build/github/android/mobile_package.required_operators.config ${REPO_ROOT}/tools/ci_build/github/android/nnapi_supported_ops.md ${REPO_ROOT}/tools/ci_build/github/apple/coreml_supported_mlprogram_ops.md ${REPO_ROOT}/tools/ci_build/github/apple/coreml_supported_neuralnetwork_ops.md diff --git a/docs/ORTMobilePackageOperatorTypeSupport.md b/docs/ORTMobilePackageOperatorTypeSupport.md deleted file mode 100644 index 6a69a2c598823..0000000000000 --- a/docs/ORTMobilePackageOperatorTypeSupport.md +++ /dev/null @@ -1,132 +0,0 @@ -# ONNX Runtime Mobile Pre-Built Package Operator and Type Support - -## Supported operators and types - -The supported operators and types are based on what is required to support float32 and quantized versions of popular models. The full list of input models used to determine this list is available [here](https://github.com/microsoft/onnxruntime/blob/main/tools/ci_build/github/android/mobile_package.required_operators.readme.txt) - -## Supported data input types - - - float - - int8_t - - uint8_t - -NOTE: Operators used to manipulate dimensions and indices will support int32 and int64. - -## Supported Operators - -|Operator|Opsets| -|--------|------| -|**ai.onnx**|| -|ai.onnx:Abs|12, 13, 14, 15| -|ai.onnx:Add|12, 13, 14, 15| -|ai.onnx:And|12, 13, 14, 15| -|ai.onnx:ArgMax|12, 13, 14, 15| -|ai.onnx:ArgMin|12, 13, 14, 15| -|ai.onnx:AveragePool|12, 13, 14, 15| -|ai.onnx:Cast|12, 13, 14, 15| -|ai.onnx:Ceil|12, 13, 14, 15| -|ai.onnx:Clip|12, 13, 14, 15| -|ai.onnx:Concat|12, 13, 14, 15| -|ai.onnx:ConstantOfShape|12, 13, 14, 15| -|ai.onnx:Conv|12, 13, 14, 15| -|ai.onnx:ConvTranspose|12, 13, 14, 15| -|ai.onnx:Cos|12, 13, 14, 15| -|ai.onnx:CumSum|12, 13, 14, 15| -|ai.onnx:DepthToSpace|12, 13, 14, 15| -|ai.onnx:DequantizeLinear|12, 13, 14, 15| -|ai.onnx:Div|12, 13, 14, 15| -|ai.onnx:DynamicQuantizeLinear|12, 13, 14, 15| -|ai.onnx:Elu|12, 13, 14, 15| -|ai.onnx:Equal|12, 13, 14, 15| -|ai.onnx:Erf|12, 13, 14, 15| -|ai.onnx:Exp|12, 13, 14, 15| -|ai.onnx:Expand|12, 13, 14, 15| -|ai.onnx:Flatten|12, 13, 14, 15| -|ai.onnx:Floor|12, 13, 14, 15| -|ai.onnx:Gather|12, 13, 14, 15| -|ai.onnx:GatherND|12, 13, 14, 15| -|ai.onnx:Gemm|12, 13, 14, 15| -|ai.onnx:GlobalAveragePool|12, 13, 14, 15| -|ai.onnx:Greater|12, 13, 14, 15| -|ai.onnx:GreaterOrEqual|12, 13, 14, 15| -|ai.onnx:HardSigmoid|12, 13, 14, 15| -|ai.onnx:Identity|12, 13, 14, 15| -|ai.onnx:If|12, 13, 14, 15| -|ai.onnx:InstanceNormalization|12, 13, 14, 15| -|ai.onnx:LRN|12, 13, 14, 15| -|ai.onnx:LayerNormalization|1| -|ai.onnx:LeakyRelu|12, 13, 14, 15| -|ai.onnx:Less|12, 13, 14, 15| -|ai.onnx:LessOrEqual|12, 13, 14, 15| -|ai.onnx:Log|12, 13, 14, 15| -|ai.onnx:LogSoftmax|12, 13, 14, 15| -|ai.onnx:Loop|12, 13, 14, 15| -|ai.onnx:MatMul|12, 13, 14, 15| -|ai.onnx:MatMulInteger|12, 13, 14, 15| -|ai.onnx:Max|12, 13, 14, 15| -|ai.onnx:MaxPool|12, 13, 14, 15| -|ai.onnx:Mean|12, 13, 14, 15| -|ai.onnx:Min|12, 13, 14, 15| -|ai.onnx:Mul|12, 13, 14, 15| -|ai.onnx:Neg|12, 13, 14, 15| -|ai.onnx:NonMaxSuppression|12, 13, 14, 15| -|ai.onnx:NonZero|12, 13, 14, 15| -|ai.onnx:Not|12, 13, 14, 15| -|ai.onnx:Or|12, 13, 14, 15| -|ai.onnx:PRelu|12, 13, 14, 15| -|ai.onnx:Pad|12, 13, 14, 15| -|ai.onnx:Pow|12, 13, 14, 15| -|ai.onnx:QLinearConv|12, 13, 14, 15| -|ai.onnx:QLinearMatMul|12, 13, 14, 15| -|ai.onnx:QuantizeLinear|12, 13, 14, 15| -|ai.onnx:Range|12, 13, 14, 15| -|ai.onnx:Reciprocal|12, 13, 14, 15| -|ai.onnx:ReduceMax|12, 13, 14, 15| -|ai.onnx:ReduceMean|12, 13, 14, 15| -|ai.onnx:ReduceMin|12, 13, 14, 15| -|ai.onnx:ReduceProd|12, 13, 14, 15| -|ai.onnx:ReduceSum|12, 13, 14, 15| -|ai.onnx:Relu|12, 13, 14, 15| -|ai.onnx:Reshape|12, 13, 14, 15| -|ai.onnx:Resize|12, 13, 14, 15| -|ai.onnx:ReverseSequence|12, 13, 14, 15| -|ai.onnx:Round|12, 13, 14, 15| -|ai.onnx:Scan|12, 13, 14, 15| -|ai.onnx:ScatterND|12, 13, 14, 15| -|ai.onnx:Shape|12, 13, 14, 15| -|ai.onnx:Sigmoid|12, 13, 14, 15| -|ai.onnx:Sin|12, 13, 14, 15| -|ai.onnx:Size|12, 13, 14, 15| -|ai.onnx:Slice|12, 13, 14, 15| -|ai.onnx:Softmax|12, 13, 14, 15| -|ai.onnx:SpaceToDepth|12, 13, 14, 15| -|ai.onnx:Split|12, 13, 14, 15| -|ai.onnx:Sqrt|12, 13, 14, 15| -|ai.onnx:Squeeze|12, 13, 14, 15| -|ai.onnx:Sub|12, 13, 14, 15| -|ai.onnx:Sum|12, 13, 14, 15| -|ai.onnx:Tanh|12, 13, 14, 15| -|ai.onnx:ThresholdedRelu|12, 13, 14, 15| -|ai.onnx:Tile|12, 13, 14, 15| -|ai.onnx:TopK|12, 13, 14, 15| -|ai.onnx:Transpose|12, 13, 14, 15| -|ai.onnx:Unique|12, 13, 14, 15| -|ai.onnx:Unsqueeze|12, 13, 14, 15| -|ai.onnx:Where|12, 13, 14, 15| -||| -|**com.microsoft**|| -|com.microsoft:DynamicQuantizeMatMul|1| -|com.microsoft:FusedConv|1| -|com.microsoft:FusedGemm|1| -|com.microsoft:FusedMatMul|1| -|com.microsoft:Gelu|1| -|com.microsoft:MatMulIntegerToFloat|1| -|com.microsoft:NhwcMaxPool|1| -|com.microsoft:QLinearAdd|1| -|com.microsoft:QLinearAveragePool|1| -|com.microsoft:QLinearConv|1| -|com.microsoft:QLinearGlobalAveragePool|1| -|com.microsoft:QLinearLeakyRelu|1| -|com.microsoft:QLinearMul|1| -|com.microsoft:QLinearSigmoid|1| -||| diff --git a/tools/ci_build/github/android/mobile_package.required_operators.config b/tools/ci_build/github/android/mobile_package.required_operators.config deleted file mode 100644 index 6a6ba8c3c90e7..0000000000000 --- a/tools/ci_build/github/android/mobile_package.required_operators.config +++ /dev/null @@ -1,46 +0,0 @@ -# Android package for ORT Mobile operator and type reduction configuration -# -# The list of operators was generated from: -# - the ONNX operators use by the tf2onnx tflite converter -# - the operators used in a set of tflite models from tfhub, the tflite examples, and the mlperf mobile models -# - models were optimized with optimizations set to 'basic', 'extended' and 'all' -# - see the readme file for full details - -# allow float, int8, uint8. operators that manipulate shapes or indices have int32 and int64 enabled internally. -!globally_allowed_types;float,int8_t,uint8_t - -# ops used by the tf2onnx tflite converter. -ai.onnx;12,13,14,15;Abs,Add,And,ArgMax,ArgMin,AveragePool,Cast,Ceil,Clip,Concat,ConstantOfShape,Conv,ConvTranspose,Cos,CumSum,DepthToSpace,DequantizeLinear,Div,DynamicQuantizeLinear,Elu,Equal,Exp,Expand,Flatten,Floor,Gather,GatherND,Gemm,Greater,GreaterOrEqual,Identity,If,LRN,LeakyRelu,Less,LessOrEqual,Log,LogSoftmax,Loop,MatMul,Max,MaxPool,Mean,Min,Mul,Neg,NonMaxSuppression,NonZero,Not,Or,PRelu,Pad,Pow,QuantizeLinear,Range,Reciprocal,ReduceMax,ReduceMean,ReduceMin,ReduceProd,ReduceSum,Relu,Reshape,Resize,ReverseSequence,Round,ScatterND,Shape,Sigmoid,Sin,Size,Slice,Softmax,SpaceToDepth,Split,Sqrt,Squeeze,Sub,Sum,Tanh,ThresholdedRelu,Tile,TopK,Transpose,Unique,Unsqueeze,Where - -# other ops found in test models -ai.onnx;12,13,14,15;Erf,GlobalAveragePool,InstanceNormalization,HardSigmoid,MatMulInteger,QLinearConv,QLinearMatMul - -# Control flow ops -# - If and Loop are covered by the tflite converter list -# - Scan tends to be used in speech models (it's more efficient than Loop) so include it for support of those -ai.onnx;12,13,14,15;Scan - -# Changed ONNX ops by opset version for the above ops. This list is to provide context as to how much was added -# for each additional opset we support. -# -# opset 13 -# Abs,Add,ArgMax,ArgMin,Cast,Ceil,Clip,Concat,DepthToSpace,DequantizeLinear,Div,Equal,Erf,Exp,Expand,Flatten,Floor, -# Gather,GatherND,Gemm,Greater,Identity,If,LRN,Less,Log,LogSoftmax,Loop,MatMul,Max,Mean,Min,Mul,Neg,NonZero,Pad, -# Pow,QuantizeLinear,Reciprocal,ReduceMax,ReduceMean,ReduceMin,ReduceProd,ReduceSum,Relu,Reshape,Resize, -# ScatterND,Shape,Sigmoid,Size,Slice,Softmax,SpaceToDepth,Split,Sqrt,Squeeze,Sub,Sum,Tanh,Tile,Transpose,Unsqueeze -# opset 14 -# Add,CumSum,Div,Identity,Mul,Relu,Reshape,Sub -# opset 15 -# Pow,Shape - - -# internal ops added by optimizers -# Note: LayerNormalization is an internal op even though it is (incorrectly) registered in the ONNX domain. -ai.onnx;1;LayerNormalization -com.microsoft;1;DynamicQuantizeMatMul,FusedConv,FusedGemm,FusedMatMul,Gelu,MatMulIntegerToFloat,NhwcMaxPool,QLinearAdd,QLinearAveragePool,QLinearConv,QLinearGlobalAveragePool,QLinearMul,QLinearSigmoid - -# NHWC transformer also uses this, so assuming it's valuable enough to include -com.microsoft;1;QLinearLeakyRelu - -# Quantized contrib ops that are registered but no usage was found. Excluding for now. -# com.microsoft;1;DynamicQuantizeLSTM,QAttention diff --git a/tools/ci_build/github/android/mobile_package.required_operators.readme.txt b/tools/ci_build/github/android/mobile_package.required_operators.readme.txt deleted file mode 100644 index 9e60cba4a42f1..0000000000000 --- a/tools/ci_build/github/android/mobile_package.required_operators.readme.txt +++ /dev/null @@ -1,82 +0,0 @@ -The required operators config file was generated from a number of models (details below), with optimizations run using 'all', 'extended' and 'basic'. -Following that, some additional operators were added, as per the comments in the config file. - -The global types to support were selected to support quantized and float32 models -Additionally there is internal 'required' type support for int32 and int64_t in selected operators that work with the dimensions in a shape or indices so that we don't need to enable those types at a global level. - -Models used as input (Converted using tf2onnx in early March 2021): - Models from TF Lite Examples https://www.tensorflow.org/lite/examples - - lite-model_deeplabv3_1_metadata_2.tflite.onnx - - lite-model_esrgan-tf2_1.tflite.onnx - - lite-model_mobilebert_1_metadata_1.tflite.onnx - - mnist.tflite.onnx - - mobilenet_v1_1.0_224_quant.tflite.onnx - - model_history10_top100.tflite.onnx - - posenet_mobilenet_float_075_1_default_1.tflite.onnx - - posenet_mobilenet_v1_100_257x257_multi_kpt_stripped.tflite.onnx - - ssd_mobilenet_v1_1_metadata_1.tflite.onnx - - text_classification_v2.tflite.onnx - -Assorted models from TF Hub that were able to be converted with tf2onnx - TFLite v1 https://tfhub.dev/s?deployment-format=lite&tf-version=tf1 - - efficientnet_lite1_fp32_2.tflite.onnx - - efficientnet_lite1_int8_2.tflite.onnx - - efficientnet_lite4_fp32_2.tflite.onnx - - efficientnet_lite4_int8_2.tflite.onnx - - lite-model_aiy_vision_classifier_birds_V1_3.tflite.onnx - - lite-model_aiy_vision_classifier_food_V1_1.tflite.onnx - - lite-model_aiy_vision_classifier_plants_V1_3.tflite.onnx - - lite-model_midas_v2_1_small_1_lite_1.tflite.onnx - - lite-model_object_detection_mobile_object_labeler_v1_1.tflite.onnx - - magenta_arbitrary-image-stylization-v1-256_int8_prediction_1.tflite.onnx - - magenta_arbitrary-image-stylization-v1-256_int8_transfer_1.tflite.onnx - - object_detection_mobile_object_localizer_v1_1_default_1.tflite.onnx - - TFLite v2 https://tfhub.dev/s?deployment-format=lite&tf-version=tf2 - - tf2\albert_lite_base_squadv1_1.tflite.onnx - - tf2\lite-model_disease-classification_1.tflite.onnx - - tf2\lite-model_efficientdet_lite0_detection_default_1.tflite.onnx - - tf2\lite-model_efficientdet_lite0_int8_1.tflite.onnx - - tf2\lite-model_efficientdet_lite1_detection_default_1.tflite.onnx - - tf2\lite-model_efficientdet_lite2_detection_default_1.tflite.onnx - - tf2\lite-model_efficientdet_lite3_detection_default_1.tflite.onnx - - tf2\lite-model_efficientdet_lite4_detection_default_1.tflite.onnx - - tf2\lite-model_esrgan-tf2_1.tflite.onnx - - tf2\lite-model_german-mbmelgan_lite_1.tflite.onnx - - tf2\lite-model_nonsemantic-speech-benchmark_trill-distilled_1.tflite.onnx - - tf2\lite-model_yamnet_tflite_1.tflite.onnx - -Models from MLPerf Mobile - (mainly models converted from TFLite and quantized in different ways, but some from TF for completeness as those also have batch handling) - - deeplabv3_mnv2_ade20k_float-int8.onnx - - deeplabv3_mnv2_ade20k_float.onnx - - deeplabv3_mnv2_ade20k-qdq.onnx - - mobilebert-int8.onnx - - mobilebert-qdq.onnx - - mobilebert.onnx - - mobiledet-int8.onnx - - mobiledet-qdq.onnx - - mobiledet.onnx - - mobilenet_edgetpu_224_1.0_float-int8.onnx - - mobilenet_edgetpu_224_1.0_float.onnx - - mobilenet_edgetpu_224_1.0-qdq.onnx - - mobilenet_v1_1.0_224.opset12.onnx - - resnet50_v1-int8.onnx - - resnet50_v1.onnx - - ssd_mobilenet_v2_300_float-int8.onnx - - ssd_mobilenet_v2_300_float.onnx - - ssd_mobilenet_v2_300-qdq.onnx - -Other - Mobilenet v2 and v3 from pytorch - - https://pytorch.org/vision/stable/models.html - - pytorch.mobilenet_v2_float.onnx - - pytorch.mobilenet_v2_uint8.onnx - - pytorch.mobilenet_v3_small.onnx - Other assorted pytorch models - - Huggingface mobilebert-uncased (https://huggingface.co/transformers/serialization.html, https://huggingface.co/google/mobilebert-uncased) - - SuperResolution (https://pytorch.org/tutorials/advanced/super_resolution_with_onnxruntime.html) - - DeepLabV3 (https://pytorch.org/tutorials/beginner/deeplabv3_on_android.html) - - EfficientNet (https://github.com/lukemelas/EfficientNet-PyTorch) - - SSD Mobilenet V1 and V2 (https://github.com/qfgaohao/pytorch-ssd) - - Wav2Vec 2.0 (adapted from https://github.com/pytorch/ios-demo-app/blob/f2b9aa196821c136d3299b99c5dd592de1fa1776/SpeechRecognition/create_wav2vec2.py) diff --git a/tools/ci_build/github/azure-pipelines/binary-size-checks-pipeline.yml b/tools/ci_build/github/azure-pipelines/binary-size-checks-pipeline.yml index e9762bc312455..74866cfd59b52 100644 --- a/tools/ci_build/github/azure-pipelines/binary-size-checks-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/binary-size-checks-pipeline.yml @@ -13,21 +13,9 @@ resources: ref: 5eda9aded5462201e6310105728d33016e637ea7 stages: - -# checks enabled in all builds - - template: templates/android-binary-size-check-stage.yml parameters: Name: MinimalBaseline BuildConfigFile: "tools/ci_build/github/linux/ort_minimal/build_check_binsize_config/android_minimal_baseline.config" BinarySizeThresholdInBytes: 1306224 DoBuildWithDebugInfo: ${{ parameters.DoBuildWithDebugInfo }} - -# checks excluded from PR builds - -- ${{ if ne(variables['Build.Reason'], 'PullRequest') }}: - - template: templates/android-binary-size-check-stage.yml - parameters: - Name: MinimalWithMobilePackageOps - BuildConfigFile: "tools/ci_build/github/linux/ort_minimal/build_check_binsize_config/android_minimal_with_mobile_package_ops.config" - DoBuildWithDebugInfo: ${{ parameters.DoBuildWithDebugInfo }} diff --git a/tools/ci_build/github/linux/ort_minimal/build_check_binsize_config/android_minimal_with_mobile_package_ops.config b/tools/ci_build/github/linux/ort_minimal/build_check_binsize_config/android_minimal_with_mobile_package_ops.config deleted file mode 100644 index dbebec5788ddb..0000000000000 --- a/tools/ci_build/github/linux/ort_minimal/build_check_binsize_config/android_minimal_with_mobile_package_ops.config +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "minimal-with-mobile-package-ops", - "os": "android", - "arch": "arm64-v8a", - "build_params": [ - "--enable_lto", - "--android", - "--android_sdk_path=/android_home", - "--android_ndk_path=/ndk_home", - "--android_abi=arm64-v8a", - "--android_api=29", - "--minimal_build", - "--build_shared_lib", - "--build_java", - "--disable_ml_ops", - "--disable_exceptions", - "--include_ops_by_config=/onnxruntime_src/tools/ci_build/github/android/mobile_package.required_operators.config" - ] -} diff --git a/tools/python/gen_ort_mobile_pkg_doc.py b/tools/python/gen_ort_mobile_pkg_doc.py deleted file mode 100644 index 482cb05bb50b9..0000000000000 --- a/tools/python/gen_ort_mobile_pkg_doc.py +++ /dev/null @@ -1,97 +0,0 @@ -import argparse -import os -import pathlib - -from util import reduced_build_config_parser -from util.ort_format_model.operator_type_usage_processors import GloballyAllowedTypesOpTypeImplFilter - - -def generate_docs(output_file, required_ops, op_type_impl_filter): - with open(output_file, "w") as out: - out.write("# ONNX Runtime Mobile Pre-Built Package Operator and Type Support\n\n") - - # Description - out.write("## Supported operators and types\n\n") - out.write( - "The supported operators and types are based on what is required to support float32 and quantized " - "versions of popular models. The full list of input models used to determine this list is available " - "[here](https://github.com/microsoft/onnxruntime/blob/main/tools/ci_build/github/android/mobile_package" - ".required_operators.readme.txt)" - ) - out.write("\n\n") - - # Globally supported types - out.write("## Supported data input types\n\n") - assert op_type_impl_filter.__class__ is GloballyAllowedTypesOpTypeImplFilter - global_types = op_type_impl_filter.global_type_list() - for type in sorted(global_types): - out.write(f" - {type}\n") - out.write("\n") - out.write("NOTE: Operators used to manipulate dimensions and indices will support int32 and int64.\n\n") - - domain_op_opsets = [] - for domain in sorted(required_ops.keys()): - op_opsets = {} - domain_op_opsets.append((domain, op_opsets)) - for opset in sorted(required_ops[domain].keys()): - str_opset = str(opset) - for op in required_ops[domain][opset]: - op_with_domain = f"{domain}:{op}" - if op_with_domain not in op_opsets: - op_opsets[op_with_domain] = [] - - op_opsets[op_with_domain].append(str_opset) - - out.write("## Supported Operators\n\n") - out.write("|Operator|Opsets|\n") - out.write("|--------|------|\n") - for domain, op_opsets in domain_op_opsets: - out.write(f"|**{domain}**||\n") - for op in sorted(op_opsets.keys()): - out.write("|{}|{}|\n".format(op, ", ".join(op_opsets[op]))) - out.write("|||\n") - - -def main(): - script_dir = os.path.dirname(os.path.realpath(__file__)) - - parser = argparse.ArgumentParser( - description="ONNX Runtime Mobile Pre-Built Package Operator and Type Support Documentation Generator", - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - ) - - default_config_path = pathlib.Path( - os.path.join(script_dir, "../ci_build/github/android/mobile_package.required_operators.config") - ).resolve() - - default_output_path = pathlib.Path( - os.path.join(script_dir, "../../docs/ORTMobilePackageOperatorTypeSupport.md") - ).resolve() - - parser.add_argument( - "--config_path", - help="Path to build configuration used to generate package.", - required=False, - type=pathlib.Path, - default=default_config_path, - ) - - parser.add_argument( - "--output_path", - help="output markdown file path", - required=False, - type=pathlib.Path, - default=default_output_path, - ) - - args = parser.parse_args() - config_file = args.config_path.resolve(strict=True) # must exist so strict=True - output_path = args.output_path.resolve() - - enable_type_reduction = True - required_ops, op_type_impl_filter = reduced_build_config_parser.parse_config(config_file, enable_type_reduction) - generate_docs(output_path, required_ops, op_type_impl_filter) - - -if __name__ == "__main__": - main() diff --git a/tools/python/util/mobile_helpers/check_model_can_use_ort_mobile_pkg.py b/tools/python/util/mobile_helpers/check_model_can_use_ort_mobile_pkg.py deleted file mode 100644 index 23bfce2e1c64d..0000000000000 --- a/tools/python/util/mobile_helpers/check_model_can_use_ort_mobile_pkg.py +++ /dev/null @@ -1,301 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. - -# Helper script that will check if the types and operators used in an ONNX model -# are supported by the pre-built ORT Mobile package. - -import argparse -import logging -import pathlib -import sys - -import onnx - -from ..onnx_model_utils import ModelProtoWithShapeInfo, get_opsets_imported -from ..reduced_build_config_parser import parse_config - -cpp_to_tensorproto_type = { - "float": 1, - "uint8_t": 2, - "int8_t": 3, - "uint16_t": 4, - "int16_t": 5, - "int32_t": 6, - "int64_t": 7, - "std::string": 8, - "bool": 9, - "MLFloat16": 10, - "double": 11, - "uint32_t": 12, - "uint64_t": 13, - "Complex64": 14, # not supported by ORT - "Complex128": 15, # not supported by ORT - "BFloat16": 16, -} - -tensorproto_type_to_cpp = {v: k for k, v in cpp_to_tensorproto_type.items()} - - -def check_graph(graph, opsets, required_ops, global_types, special_types, unsupported_ops, logger): - """ - Check the graph and any subgraphs for usage of types or operators which we know are not supported. - :param graph: Graph to process. - :param opsets: Map of domain to opset version that the model imports. - :param required_ops: Operators that are included in the pre-built package. - :param global_types: Types globally enabled in the pre-built package. - :param special_types: Types that are always enabled for a subset of operators and are _usually_ supported but are - not guaranteed to be. We would need to add a lot of infrastructure to know for sure so - currently we treat them as supported. - :param unsupported_ops: Set of unsupported operators that were found. - :param logger: Logger for diagnostic output. - :return: Returns whether the graph uses unsupported operators or types. - """ - has_unsupported_types = False - value_info_map = {vi.name: vi for vi in graph.value_info} - - def _is_type_supported(value_info, description): - is_supported = True - type_name = value_info.type.WhichOneof("value") - if type_name == "tensor_type": - t = value_info.type.tensor_type.elem_type - if t not in global_types and t not in special_types: - cpp_type = tensorproto_type_to_cpp[t] - logger.debug(f"Element type {cpp_type} of {description} is not supported.") - is_supported = False - else: - # we don't support sequences, map, sparse tensors, or optional types in the pre-built package - logger.debug(f"Data type {type_name} of {description} is not supported.") - is_supported = False - - return is_supported - - def _input_output_is_supported(value_info, input_output): - return _is_type_supported(value_info, f"graph {input_output} {value_info.name}") - - # node outputs are simpler to check. - # node inputs have a much wider mix of types, some of which come from initializers and most likely are always - # enabled as we generally do type reduction on the user data input to the operator and not the weights/etc. which - # come from initializers. - def _node_output_is_supported(name): - is_supported = True - if name in value_info_map: - vi = value_info_map[name] - is_supported = _is_type_supported(vi, f"node output {name}") - else: - # we don't have type info so ignore - pass - - return is_supported - - for i in graph.input: - if not _input_output_is_supported(i, "input"): - has_unsupported_types = True - - for o in graph.output: - if not _input_output_is_supported(o, "output"): - has_unsupported_types = True - - for node in graph.node: - # required_ops are map of [domain][opset] to set of op_type names. '' == ai.onnx - domain = node.domain or "ai.onnx" - - # special case Constant as we will convert to an initializer during model load - if domain == "ai.onnx" and node.op_type == "Constant": - continue - - # some models don't have complete imports. use 1 as a default as that's valid for custom domains and should - # result in an error for any others. not sure why ONNX or ORT validation allows this though. - opset = opsets.get(domain, 1) - if ( - domain not in required_ops - or opset not in required_ops[domain] - or node.op_type not in required_ops[domain][opset] - ): - unsupported_ops.add(f"{domain}:{opset}:{node.op_type}") - - for output_name in node.output: - if not _node_output_is_supported(output_name): - has_unsupported_types = True - - # recurse into subgraph for control flow nodes (Scan/Loop/If) - for attr in node.attribute: - if attr.HasField("g"): - check_graph(attr.g, opsets, required_ops, global_types, special_types, unsupported_ops, logger) - - return has_unsupported_types or unsupported_ops - - -def _get_global_tensorproto_types(op_type_impl_filter, logger: logging.Logger): - """ - Map the globally supported types (C++) to onnx.TensorProto.DataType values used in the model - See https://github.com/onnx/onnx/blob/1faae95520649c93ae8d0b403816938a190f4fa7/onnx/onnx.proto#L485 - - Additionally return a set of types we special case as being able to generally be considered as supported. - :param op_type_impl_filter: type filter from reduced build configuration parser - :param logger: Logger - :return: tuple of globally enabled types and special cased types - """ - global_cpp_types = op_type_impl_filter.global_type_list() - global_onnx_tensorproto_types = set() - - for t in global_cpp_types: - if t in cpp_to_tensorproto_type: - global_onnx_tensorproto_types.add(cpp_to_tensorproto_type[t]) - else: - logger.error(f"Error: Unexpected data type of {t} in package build config's globally enabled types.") - sys.exit(-1) - - # a subset of operators require int32 and int64 to always be enabled, as those types are used for dimensions in - # shapes and indices. - # additionally we have a number of operators (e.g. Not, Where) that always require the use of bool. - # this _may_ mean values involving these types can be processed, but without adding a lot more code we don't know - # for sure. - special_types = [ - cpp_to_tensorproto_type["int32_t"], - cpp_to_tensorproto_type["int64_t"], - cpp_to_tensorproto_type["bool"], - ] - - return global_onnx_tensorproto_types, special_types - - -def get_default_config_path(): - # get default path to config that was used to create the pre-built package. - script_dir = pathlib.Path(__file__).parent - local_config = script_dir / "mobile_package.required_operators.config" - - # if we're running in the ORT python package the file should be local. otherwise assume we're running from the - # ORT repo - if local_config.exists(): - default_config_path = local_config - else: - ort_root = script_dir.parents[3] - default_config_path = ( - ort_root / "tools" / "ci_build" / "github" / "android" / "mobile_package.required_operators.config" - ) - - return default_config_path - - -def run_check_with_model( - model_with_type_info: onnx.ModelProto, mobile_pkg_build_config: pathlib.Path, logger: logging.Logger -): - """ - Check if an ONNX model can be used with the ORT Mobile pre-built package. - :param model_with_type_info: ONNX model that has had ONNX shape inferencing run on to add type/shape information. - :param mobile_pkg_build_config: Configuration file used to build the ORT Mobile package. - :param logger: Logger for output - :return: True if supported - """ - if not mobile_pkg_build_config: - mobile_pkg_build_config = get_default_config_path() - - enable_type_reduction = True - config_path = str(mobile_pkg_build_config.resolve(strict=True)) - required_ops, op_type_impl_filter = parse_config(config_path, enable_type_reduction) - global_onnx_tensorproto_types, special_types = _get_global_tensorproto_types(op_type_impl_filter, logger) - - # get the opset imports - opsets = get_opsets_imported(model_with_type_info) - - # If the ONNX opset of the model is not supported we can recommend using our tools to update that first. - supported_onnx_opsets = set(required_ops["ai.onnx"].keys()) - # we have a contrib op that is erroneously in the ai.onnx domain with opset 1. manually remove that incorrect value - supported_onnx_opsets.remove(1) - onnx_opset_model_uses = opsets["ai.onnx"] - if onnx_opset_model_uses not in supported_onnx_opsets: - logger.info(f"Model uses ONNX opset {onnx_opset_model_uses}.") - logger.info(f"The pre-built package only supports ONNX opsets {sorted(supported_onnx_opsets)}.") - logger.info( - "Please try updating the ONNX model opset to a supported version using " - "python -m onnxruntime.tools.onnx_model_utils.update_onnx_opset ..." - ) - - return False - - unsupported_ops = set() - logger.debug( - "Checking if the data types and operators used in the model are supported in the pre-built ORT package..." - ) - unsupported = check_graph( - model_with_type_info.graph, - opsets, - required_ops, - global_onnx_tensorproto_types, - special_types, - unsupported_ops, - logger, - ) - - if unsupported_ops: - logger.info("Unsupported operators:") - for entry in sorted(unsupported_ops): - logger.info(" " + entry) # noqa: G003 - - if unsupported: - logger.info("\nModel is not supported by the pre-built package due to unsupported types and/or operators.") - logger.info( - "Please see https://onnxruntime.ai/docs/install/#install-on-web-and-mobile for information " - "on what is supported in the pre-built package." - ) - logger.info( - "The 'full' ORT package for Android (onnxruntime-android) or iOS (onnxruntime-{objc|c}) could be used, " - "or a custom build of ONNX Runtime will be required if binary size is critical. Please see " - "https://onnxruntime.ai/docs/build/custom.html for details on performing that." - ) - else: - logger.info("Model should work with the pre-built package.") - - logger.info("---------------\n") - - return not unsupported - - -def run_check(model_path: pathlib.Path, mobile_pkg_build_config: pathlib.Path, logger: logging.Logger): - """ - Check if an ONNX model will be able to be used with the ORT Mobile pre-built package. - :param model_path: Path to ONNX model. - :param mobile_pkg_build_config: Configuration file used to build the ORT Mobile package. - :param logger: Logger for output - :return: True if supported - """ - logger.info( - f"Checking if pre-built ORT Mobile package can be used with {model_path} once model is " - "converted from ONNX to ORT format using onnxruntime.tools.convert_onnx_models_to_ort..." - ) - - model_file = model_path.resolve(strict=True) - - # we need to run shape inferencing to populate that type info for node outputs. - # we will get warnings if the model uses ORT contrib ops (ONNX does not have shape inferencing for those), - # and shape inferencing will be lost downstream of those. - # TODO: add support for checking ORT format model as it will have full type/shape info for all nodes - model_wrapper = ModelProtoWithShapeInfo(model_file) - return run_check_with_model(model_wrapper.model_with_shape_info, mobile_pkg_build_config, logger) - - -def main(): - parser = argparse.ArgumentParser( - description="Check if model can be run using the ONNX Runtime Mobile Pre-Built Package", - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - ) - - parser.add_argument( - "--config_path", - help="Path to required operators and types configuration used to build the pre-built ORT mobile package.", - required=False, - type=pathlib.Path, - default=get_default_config_path(), - ) - - parser.add_argument("model_path", help="Path to ONNX model to check", type=pathlib.Path) - - args = parser.parse_args() - - logger = logging.getLogger("default") - logger.setLevel(logging.INFO) - run_check(args.model_path, args.config_path, logger) - - -if __name__ == "__main__": - main() From 1f907a23f0b863b8e9f2d307d667b913c002c6e6 Mon Sep 17 00:00:00 2001 From: Yifan Li <109183385+yf711@users.noreply.github.com> Date: Mon, 5 Aug 2024 16:41:56 -0700 Subject: [PATCH 05/15] [EP Perf] Update cmake (#21624) ### Description update script with cmake 3.30 to unblock EP Perf ### Motivation and Context --- dockerfiles/scripts/install_common_deps.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dockerfiles/scripts/install_common_deps.sh b/dockerfiles/scripts/install_common_deps.sh index 786a6f076a71b..41bdc068d8cde 100644 --- a/dockerfiles/scripts/install_common_deps.sh +++ b/dockerfiles/scripts/install_common_deps.sh @@ -21,6 +21,6 @@ pip install "wheel>=0.35.1" rm -rf /opt/miniconda/pkgs # Dependencies: cmake -wget --quiet https://github.com/Kitware/CMake/releases/download/v3.27.3/cmake-3.27.3-linux-x86_64.tar.gz -tar zxf cmake-3.27.3-linux-x86_64.tar.gz -rm -rf cmake-3.27.3-linux-x86_64.tar.gz +wget --quiet https://github.com/Kitware/CMake/releases/download/v3.30.1/cmake-3.30.1-linux-x86_64.tar.gz +tar zxf cmake-3.30.1-linux-x86_64.tar.gz +rm -rf cmake-3.30.1-linux-x86_64.tar.gz From f6f9657fb61bd2e739ff96abcb42c5f42d7c4957 Mon Sep 17 00:00:00 2001 From: liqun Fu Date: Mon, 5 Aug 2024 20:52:26 -0700 Subject: [PATCH 06/15] Fix typos so to call correct vnni functions under vnni condition (#21625) ### Description Fix 2 typos in mlas avx 4bit gemm implementation to call correct vnni functions under vnni condition ### Motivation and Context needed for 1.19.0 release Signed-off-by: liqunfu --- .../core/mlas/lib/sqnbitgemm_kernel_avx512_int8_blklen16.h | 4 ++-- .../core/mlas/lib/sqnbitgemm_kernel_avx512_int8_blklen32.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx512_int8_blklen16.h b/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx512_int8_blklen16.h index 3cd610796a5e3..bb14babd6c2b1 100644 --- a/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx512_int8_blklen16.h +++ b/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx512_int8_blklen16.h @@ -679,9 +679,9 @@ Q4Int8GemmR1xC1BlkLen16Avx512( const __m512i av_01_epi8 = _mm512_loadu_si512((const __m512i*)(QuantAPtr + 64)); if constexpr (vnni) { - accumulate_blklen16_r1c1blk8_avx512(av_00_epi8, av_01_epi8, QuantBDataPtr, QuantAScalePtr, QuantBScalePtr, acc0); - } else { accumulate_blklen16_r1c1blk8_avx512vnni(av_00_epi8, av_01_epi8, QuantBDataPtr, QuantAScalePtr, QuantBScalePtr, acc0); + } else { + accumulate_blklen16_r1c1blk8_avx512(av_00_epi8, av_01_epi8, QuantBDataPtr, QuantAScalePtr, QuantBScalePtr, acc0); } QuantAPtr += BlkLen16 * PerAccuBlk8; diff --git a/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx512_int8_blklen32.h b/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx512_int8_blklen32.h index ca12cc14a7875..e9df6b952bd27 100644 --- a/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx512_int8_blklen32.h +++ b/onnxruntime/core/mlas/lib/sqnbitgemm_kernel_avx512_int8_blklen32.h @@ -721,7 +721,7 @@ Q4Int8GemmR1xC1BlkLen32Avx512( accumulate_blklen32_r1c1blk4_avx512vnni(av_00_epi8, av_01_epi8, QuantBDataPtr, QuantAScalePtr, QuantBScalePtr, acc0); } else { - accumulate_blklen32_r1c1blk4_avx512vnni(av_00_epi8, av_01_epi8, QuantBDataPtr, QuantAScalePtr, QuantBScalePtr, acc0); + accumulate_blklen32_r1c1blk4_avx512(av_00_epi8, av_01_epi8, QuantBDataPtr, QuantAScalePtr, QuantBScalePtr, acc0); } QuantAPtr += BlkLen32 * PerAccuBlk4; From 0d1da41ca82a0e90f71e987c25ef196a97f83c51 Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Tue, 6 Aug 2024 21:37:09 +0800 Subject: [PATCH 07/15] Fix docker image layer caching to avoid redundant docker building and transient connection exceptions. (#21612) ### Description Improve docker commands to make docker image layer caching works. It can make docker building faster and more stable. So far, A100 pool's system disk is too small to use docker cache. We won't use pipeline cache for docker image and remove some legacy code. ### Motivation and Context There are often an exception of ``` 64.58 + curl https://nodejs.org/dist/v18.17.1/node-v18.17.1-linux-x64.tar.gz -sSL --retry 5 --retry-delay 30 --create-dirs -o /tmp/src/node-v18.17.1-linux-x64.tar.gz --fail 286.4 curl: (92) HTTP/2 stream 0 was not closed cleanly: INTERNAL_ERROR (err 2) ``` Because Onnxruntime pipeline have been sending too many requests to download Nodejs in docker building. Which is the major reason of pipeline failing now In fact, docker image layer caching never works. We can always see the scrips are still running ``` #9 [3/5] RUN cd /tmp/scripts && /tmp/scripts/install_centos.sh && /tmp/scripts/install_deps.sh && rm -rf /tmp/scripts #9 0.234 /bin/sh: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8) #9 0.235 /bin/sh: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8) #9 0.235 /tmp/scripts/install_centos.sh: line 1: !/bin/bash: No such file or directory #9 0.235 ++ '[' '!' -f /etc/yum.repos.d/microsoft-prod.repo ']' #9 0.236 +++ tr -dc 0-9. #9 0.236 +++ cut -d . -f1 #9 0.238 ++ os_major_version=8 .... #9 60.41 + curl https://nodejs.org/dist/v18.17.1/node-v18.17.1-linux-x64.tar.gz -sSL --retry 5 --retry-delay 30 --create-dirs -o /tmp/src/node-v18.17.1-linux-x64.tar.gz --fail #9 60.59 + return 0 ... ``` This PR is improving the docker command to make image layer caching work. Thus, CI won't send so many redundant request of downloading NodeJS. ``` #9 [2/5] ADD scripts /tmp/scripts #9 CACHED #10 [3/5] RUN cd /tmp/scripts && /tmp/scripts/install_centos.sh && /tmp/scripts/install_deps.sh && rm -rf /tmp/scripts #10 CACHED #11 [4/5] RUN adduser --uid 1000 onnxruntimedev #11 CACHED #12 [5/5] WORKDIR /home/onnxruntimedev #12 CACHED ``` ###Reference https://docs.docker.com/build/drivers/ --------- Co-authored-by: Yi Zhang --- tools/ci_build/get_docker_image.py | 24 ++----- .../azure-pipelines/bigmodels-ci-pipeline.yml | 1 + .../templates/c-api-linux-cpu.yml | 8 +-- .../templates/get-docker-image-steps.yml | 64 ++++++------------- .../inference/aarch64/default/cpu/Dockerfile | 2 +- .../inference/x86_64/default/cpu/Dockerfile | 2 +- 6 files changed, 32 insertions(+), 69 deletions(-) diff --git a/tools/ci_build/get_docker_image.py b/tools/ci_build/get_docker_image.py index 99ecaf677f339..a3f603b0beda4 100755 --- a/tools/ci_build/get_docker_image.py +++ b/tools/ci_build/get_docker_image.py @@ -98,17 +98,19 @@ def main(): ) if use_container_registry: + run(args.docker_path, "buildx", "create", "--driver=docker-container", "--name=container_builder") run( args.docker_path, "--log-level", "error", "buildx", "build", - "--push", + "--load", "--tag", full_image_name, - "--cache-from", - full_image_name, + "--cache-from=type=registry,ref=" + full_image_name, + "--builder", + "container_builder", "--build-arg", "BUILDKIT_INLINE_CACHE=1", *shlex.split(args.docker_build_args), @@ -116,24 +118,10 @@ def main(): args.dockerfile, args.context, ) - elif args.use_imagecache: - log.info("Building image with pipeline cache...") run( args.docker_path, - "--log-level", - "error", - "buildx", - "build", - "--tag", - full_image_name, - "--cache-from", + "push", full_image_name, - "--build-arg", - "BUILDKIT_INLINE_CACHE=1", - *shlex.split(args.docker_build_args), - "-f", - args.dockerfile, - args.context, ) else: log.info("Building image...") diff --git a/tools/ci_build/github/azure-pipelines/bigmodels-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/bigmodels-ci-pipeline.yml index a66828ee5e188..4a3532dd57fa3 100644 --- a/tools/ci_build/github/azure-pipelines/bigmodels-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/bigmodels-ci-pipeline.yml @@ -321,6 +321,7 @@ stages: --build-arg TRT_VERSION=${{ variables.linux_trt_version }} " Repository: onnxruntimeubi8packagestest_torch + UseImageCacheContainerRegistry: false UpdateDepsTxt: false - task: DownloadPackage@1 diff --git a/tools/ci_build/github/azure-pipelines/templates/c-api-linux-cpu.yml b/tools/ci_build/github/azure-pipelines/templates/c-api-linux-cpu.yml index e2b71c5c55fd2..0f4328f75e1bd 100644 --- a/tools/ci_build/github/azure-pipelines/templates/c-api-linux-cpu.yml +++ b/tools/ci_build/github/azure-pipelines/templates/c-api-linux-cpu.yml @@ -51,15 +51,15 @@ jobs: Dockerfile: tools/ci_build/github/linux/docker/inference/x86_64/default/cpu/Dockerfile Context: tools/ci_build/github/linux/docker/inference/x86_64/default/cpu DockerBuildArgs: "--build-arg BUILD_UID=$( id -u ) --build-arg BASEIMAGE=${{parameters.BaseImage}}" - Repository: onnxruntimecpubuildcentos8${{parameters.OnnxruntimeArch}} - + Repository: onnxruntimecpubuildcentos8${{parameters.OnnxruntimeArch}}_packaging + - ${{ if eq(parameters.OnnxruntimeArch, 'aarch64') }}: - template: get-docker-image-steps.yml parameters: Dockerfile: tools/ci_build/github/linux/docker/inference/aarch64/default/cpu/Dockerfile Context: tools/ci_build/github/linux/docker/inference/aarch64/default/cpu DockerBuildArgs: "--build-arg BUILD_UID=$( id -u ) --build-arg BASEIMAGE=${{parameters.BaseImage}}" - Repository: onnxruntimecpubuildcentos8${{parameters.OnnxruntimeArch}} + Repository: onnxruntimecpubuildcentos8${{parameters.OnnxruntimeArch}}_packaging UpdateDepsTxt: false - task: CmdLine@2 @@ -67,7 +67,7 @@ jobs: script: | mkdir -p $HOME/.onnx docker run --rm --volume /data/onnx:/data/onnx:ro --volume $(Build.SourcesDirectory):/onnxruntime_src --volume $(Build.BinariesDirectory):/build \ - --volume $HOME/.onnx:/home/onnxruntimedev/.onnx -e NIGHTLY_BUILD onnxruntimecpubuildcentos8${{parameters.OnnxruntimeArch}} /bin/bash -c "python3.9 \ + --volume $HOME/.onnx:/home/onnxruntimedev/.onnx -e NIGHTLY_BUILD onnxruntimecpubuildcentos8${{parameters.OnnxruntimeArch}}_packaging /bin/bash -c "python3.9 \ /onnxruntime_src/tools/ci_build/build.py --enable_lto --build_java --build_nodejs --build_dir /build --config Release \ --skip_submodule_sync --parallel --use_binskim_compliant_compile_flags --build_shared_lib ${{ parameters.AdditionalBuildFlags }} && cd /build/Release && make install DESTDIR=/build/installed" workingDirectory: $(Build.SourcesDirectory) diff --git a/tools/ci_build/github/azure-pipelines/templates/get-docker-image-steps.yml b/tools/ci_build/github/azure-pipelines/templates/get-docker-image-steps.yml index 94cdf042ec62b..5b6769685a972 100644 --- a/tools/ci_build/github/azure-pipelines/templates/get-docker-image-steps.yml +++ b/tools/ci_build/github/azure-pipelines/templates/get-docker-image-steps.yml @@ -53,6 +53,7 @@ steps: displayName: patch manylinux - script: | + docker version docker image ls docker system df displayName: Check Docker Images @@ -71,52 +72,25 @@ steps: displayName: "Get ${{ parameters.Repository }} image for ${{ parameters.Dockerfile }}" ContainerRegistry: onnxruntimebuildcache - ${{ if eq(parameters.UseImageCacheContainerRegistry, false) }}: - - task: Cache@2 - displayName: Cache Docker Image Task - inputs: - key: ' "${{ parameters.Repository }}" | "$(Build.SourceVersion)" ' - path: ${{ parameters.IMAGE_CACHE_DIR }} - restoreKeys: | - "${{ parameters.Repository }}" | "$(Build.SourceVersion)" - "${{ parameters.Repository }}" - cacheHitVar: CACHE_RESTORED - condition: eq('${{ parameters.UsePipelineCache }}', 'true') - - - script: | - test -f ${{ parameters.IMAGE_CACHE_DIR }}/cache.tar && docker load -i ${{ parameters.IMAGE_CACHE_DIR }}/cache.tar - docker image ls - displayName: Docker restore - condition: eq('${{ parameters.UsePipelineCache }}', 'true') - - - script: | - if [ ${{ parameters.UsePipelineCache}} ] - then - use_imagecache="--use_imagecache" - else - use_imagecache="" - fi - ${{ parameters.ScriptName }} \ - --dockerfile "${{ parameters.Dockerfile }}" \ - --context "${{ parameters.Context }}" \ - --docker-build-args "${{ parameters.DockerBuildArgs }}" \ - --repository "${{ parameters.Repository }}" \ - $use_imagecache - displayName: "Get ${{ parameters.Repository }} image for ${{ parameters.Dockerfile }}" - - - script: | - set -ex - mkdir -p "${{ parameters.IMAGE_CACHE_DIR }}" - docker save -o "${{ parameters.IMAGE_CACHE_DIR }}/cache.tar" ${{ parameters.Repository }} - docker image ls - docker system df - displayName: Docker save - condition: eq('${{ parameters.UsePipelineCache }}', 'true') + # the difference is no --container-registry + - template: with-container-registry-steps.yml + parameters: + Steps: + - script: | + ${{ parameters.ScriptName }} \ + --dockerfile "${{ parameters.Dockerfile }}" \ + --context "${{ parameters.Context }}" \ + --docker-build-args "${{ parameters.DockerBuildArgs }}" \ + --repository "${{ parameters.Repository }}" + displayName: "Get ${{ parameters.Repository }} image for ${{ parameters.Dockerfile }}" + ContainerRegistry: onnxruntimebuildcache - - script: | - echo ${{ parameters.IMAGE_CACHE_DIR }} - ls -lah ${{ parameters.IMAGE_CACHE_DIR }} - displayName: Display docker dir - condition: eq('${{ parameters.UsePipelineCache }}', 'true') +- script: | + docker version + docker image ls + docker system df + df -h + displayName: Check Docker Images - ${{ if and(eq(parameters.UpdateDepsTxt, true), or(eq(variables['System.CollectionId'], 'f3ad12f2-e480-4533-baf2-635c95467d29'),eq(variables['System.CollectionId'], 'bc038106-a83b-4dab-9dd3-5a41bc58f34c'))) }}: - task: PythonScript@0 diff --git a/tools/ci_build/github/linux/docker/inference/aarch64/default/cpu/Dockerfile b/tools/ci_build/github/linux/docker/inference/aarch64/default/cpu/Dockerfile index 2cd054e6246bc..ca00050121d67 100644 --- a/tools/ci_build/github/linux/docker/inference/aarch64/default/cpu/Dockerfile +++ b/tools/ci_build/github/linux/docker/inference/aarch64/default/cpu/Dockerfile @@ -5,7 +5,7 @@ ARG BASEIMAGE=arm64v8/almalinux:8 FROM $BASEIMAGE -ENV PATH /opt/rh/gcc-toolset-12/root/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +ENV PATH=/opt/rh/gcc-toolset-12/root/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ENV LANG=en_US.UTF-8 ENV LC_ALL=en_US.UTF-8 diff --git a/tools/ci_build/github/linux/docker/inference/x86_64/default/cpu/Dockerfile b/tools/ci_build/github/linux/docker/inference/x86_64/default/cpu/Dockerfile index caf9583807b62..ef28dde67617f 100644 --- a/tools/ci_build/github/linux/docker/inference/x86_64/default/cpu/Dockerfile +++ b/tools/ci_build/github/linux/docker/inference/x86_64/default/cpu/Dockerfile @@ -5,7 +5,7 @@ ARG BASEIMAGE=amd64/almalinux:8 FROM $BASEIMAGE -ENV PATH /usr/lib/jvm/msopenjdk-11/bin:/opt/rh/gcc-toolset-12/root/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +ENV PATH=/usr/lib/jvm/msopenjdk-11/bin:/opt/rh/gcc-toolset-12/root/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ENV LANG=en_US.UTF-8 ENV LC_ALL=en_US.UTF-8 ENV JAVA_HOME=/usr/lib/jvm/msopenjdk-11 From 0acefc79880ca61310815ca1ce2502668d953588 Mon Sep 17 00:00:00 2001 From: Adrian Lizarraga Date: Tue, 6 Aug 2024 09:08:48 -0700 Subject: [PATCH 08/15] [QNN EP] Update QNN SDK to 2.25 (#21623) ### Description - Update pipelines to use QNN SDK 2.25 by default - Update ifdef condition to apply workaround for QNN LayerNorm validation bug to QNN SDK 2.25 (as well as 2.24) ### Motivation and Context Use the latest QNN SDK --- .../qnn/builder/opbuilder/layer_norm_op_builder.cc | 6 +++--- .../android-arm64-v8a-QNN-crosscompile-ci-pipeline.yml | 2 +- .../azure-pipelines/c-api-noopenmp-packaging-pipelines.yml | 2 +- .../github/azure-pipelines/linux-qnn-ci-pipeline.yml | 2 +- .../github/azure-pipelines/py-packaging-pipeline.yml | 2 +- .../azure-pipelines/qnn-ep-nuget-packaging-pipeline.yml | 2 +- .../templates/jobs/download_linux_qnn_sdk.yml | 2 +- .../azure-pipelines/templates/jobs/download_win_qnn_sdk.yml | 2 +- .../github/azure-pipelines/templates/py-packaging-stage.yml | 2 +- .../github/azure-pipelines/templates/py-win-arm64-qnn.yml | 2 +- .../github/azure-pipelines/templates/py-win-x64-qnn.yml | 2 +- .../github/azure-pipelines/templates/qnn-ep-win.yml | 2 +- .../github/azure-pipelines/win-qnn-arm64-ci-pipeline.yml | 2 +- .../ci_build/github/azure-pipelines/win-qnn-ci-pipeline.yml | 2 +- 14 files changed, 16 insertions(+), 16 deletions(-) diff --git a/onnxruntime/core/providers/qnn/builder/opbuilder/layer_norm_op_builder.cc b/onnxruntime/core/providers/qnn/builder/opbuilder/layer_norm_op_builder.cc index c667aeeaa61f0..a31b15948cb7f 100644 --- a/onnxruntime/core/providers/qnn/builder/opbuilder/layer_norm_op_builder.cc +++ b/onnxruntime/core/providers/qnn/builder/opbuilder/layer_norm_op_builder.cc @@ -87,10 +87,10 @@ Status LayerNormOpBuilder::ProcessInputs(QnnModelWrapper& qnn_model_wrapper, ORT_RETURN_IF_ERROR(ProcessInput(qnn_model_wrapper, inputs[BIAS_IDX], logger, input_names)); } -#if QNN_API_VERSION_MAJOR == 2 && QNN_API_VERSION_MINOR == 17 +#if QNN_API_VERSION_MAJOR == 2 && (QNN_API_VERSION_MINOR == 17 || QNN_API_VERSION_MINOR == 18) if (!has_bias_input && IsNpuBackend(qnn_model_wrapper.GetQnnBackendType())) { - // Bias is implicit. QNN SDK 2.24 (QNN API version 2.17) has a validation bug for implicit bias inputs, so provide - // an explicit bias of all 0 (quantized int32). + // Bias is implicit. QNN SDK 2.24/2.25 (QNN API version 2.17/2.18) has a validation bug for implicit bias inputs, + // so provide an explicit bias of all 0 (quantized int32). TensorInfo x_input_info = {}; ORT_RETURN_IF_ERROR(qnn_model_wrapper.GetTensorInfo(inputs[X_IDX], x_input_info)); diff --git a/tools/ci_build/github/azure-pipelines/android-arm64-v8a-QNN-crosscompile-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/android-arm64-v8a-QNN-crosscompile-ci-pipeline.yml index c80092fc82ed5..3fba9f54f2667 100644 --- a/tools/ci_build/github/azure-pipelines/android-arm64-v8a-QNN-crosscompile-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/android-arm64-v8a-QNN-crosscompile-ci-pipeline.yml @@ -31,7 +31,7 @@ parameters: - name: QnnSdk displayName: QNN SDK version type: string - default: 2.24.0.240626 + default: 2.25.0.240728 jobs: - job: Build_QNN_EP diff --git a/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml b/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml index 51b73acd93dc8..c9210b996b84e 100644 --- a/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml +++ b/tools/ci_build/github/azure-pipelines/c-api-noopenmp-packaging-pipelines.yml @@ -62,7 +62,7 @@ parameters: - name: QnnSdk displayName: QNN SDK Version type: string - default: 2.24.0.240626 + default: 2.25.0.240728 resources: repositories: diff --git a/tools/ci_build/github/azure-pipelines/linux-qnn-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-qnn-ci-pipeline.yml index 0d67b0947be53..9282792a6b418 100644 --- a/tools/ci_build/github/azure-pipelines/linux-qnn-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-qnn-ci-pipeline.yml @@ -32,7 +32,7 @@ parameters: - name: QnnSdk displayName: QNN SDK version type: string - default: 2.24.0.240626 + default: 2.25.0.240728 jobs: - job: Build_QNN_EP 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 cd3966633d742..c7a1b595a6c6f 100644 --- a/tools/ci_build/github/azure-pipelines/py-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/py-packaging-pipeline.yml @@ -59,7 +59,7 @@ parameters: - name: qnn_sdk_version type: string displayName: 'QNN SDK version. Only for QNN packages.' - default: 2.24.0.240626 + default: 2.25.0.240728 trigger: none diff --git a/tools/ci_build/github/azure-pipelines/qnn-ep-nuget-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/qnn-ep-nuget-packaging-pipeline.yml index 7229bc5dbd114..25d50f4255cb1 100644 --- a/tools/ci_build/github/azure-pipelines/qnn-ep-nuget-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/qnn-ep-nuget-packaging-pipeline.yml @@ -2,7 +2,7 @@ parameters: - name: QnnSdk displayName: QNN SDK Version type: string - default: 2.24.0.240626 + default: 2.25.0.240728 - name: build_config displayName: Build Configuration diff --git a/tools/ci_build/github/azure-pipelines/templates/jobs/download_linux_qnn_sdk.yml b/tools/ci_build/github/azure-pipelines/templates/jobs/download_linux_qnn_sdk.yml index 734ad43e0066d..e727ec4f7ef5c 100644 --- a/tools/ci_build/github/azure-pipelines/templates/jobs/download_linux_qnn_sdk.yml +++ b/tools/ci_build/github/azure-pipelines/templates/jobs/download_linux_qnn_sdk.yml @@ -1,7 +1,7 @@ parameters: - name: QnnSDKVersion type: string - default: '2.24.0.240626' + default: '2.25.0.240728' steps: - script: | diff --git a/tools/ci_build/github/azure-pipelines/templates/jobs/download_win_qnn_sdk.yml b/tools/ci_build/github/azure-pipelines/templates/jobs/download_win_qnn_sdk.yml index 900adc9690255..912cac6fbb99e 100644 --- a/tools/ci_build/github/azure-pipelines/templates/jobs/download_win_qnn_sdk.yml +++ b/tools/ci_build/github/azure-pipelines/templates/jobs/download_win_qnn_sdk.yml @@ -1,7 +1,7 @@ parameters: - name: QnnSDKVersion type: string - default: '2.24.0.240626' + default: '2.25.0.240728' steps: - powershell: | 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 447e35244eb66..faf453140052b 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 @@ -63,7 +63,7 @@ parameters: - name: qnn_sdk_version type: string displayName: 'QNN SDK version. Only for QNN packages.' - default: 2.24.0.240626 + default: 2.25.0.240728 stages: - ${{ if eq(parameters.enable_windows_cpu, true) }}: diff --git a/tools/ci_build/github/azure-pipelines/templates/py-win-arm64-qnn.yml b/tools/ci_build/github/azure-pipelines/templates/py-win-arm64-qnn.yml index 40e8583141df8..c3a2b7be7ebd2 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-win-arm64-qnn.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-win-arm64-qnn.yml @@ -7,7 +7,7 @@ parameters: - name: QNN_SDK displayName: QNN SDK Version type: string - default: 2.24.0.240626 + default: 2.25.0.240728 - name: PYTHON_VERSION type: string diff --git a/tools/ci_build/github/azure-pipelines/templates/py-win-x64-qnn.yml b/tools/ci_build/github/azure-pipelines/templates/py-win-x64-qnn.yml index 33335bb2be2dd..5cf03a7cdd100 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-win-x64-qnn.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-win-x64-qnn.yml @@ -7,7 +7,7 @@ parameters: - name: QNN_SDK displayName: QNN SDK Version type: string - default: 2.24.0.240626 + default: 2.25.0.240728 - name: ENV_SETUP_SCRIPT type: string diff --git a/tools/ci_build/github/azure-pipelines/templates/qnn-ep-win.yml b/tools/ci_build/github/azure-pipelines/templates/qnn-ep-win.yml index 944745b69ca63..c7fd26712329c 100644 --- a/tools/ci_build/github/azure-pipelines/templates/qnn-ep-win.yml +++ b/tools/ci_build/github/azure-pipelines/templates/qnn-ep-win.yml @@ -1,5 +1,5 @@ parameters: - QnnSdk: '2.24.0.240626' + QnnSdk: '2.25.0.240728' build_config: 'RelWithDebInfo' IsReleaseBuild: false DoEsrp: false diff --git a/tools/ci_build/github/azure-pipelines/win-qnn-arm64-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-qnn-arm64-ci-pipeline.yml index e1b8b718e9928..31cdbeb99be4f 100644 --- a/tools/ci_build/github/azure-pipelines/win-qnn-arm64-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/win-qnn-arm64-ci-pipeline.yml @@ -32,7 +32,7 @@ parameters: - name: QnnSdk displayName: QNN SDK version type: string - default: 2.24.0.240626 + default: 2.25.0.240728 jobs: - job: 'build' diff --git a/tools/ci_build/github/azure-pipelines/win-qnn-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-qnn-ci-pipeline.yml index 97c4ab15095c9..54277bcb4039f 100644 --- a/tools/ci_build/github/azure-pipelines/win-qnn-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/win-qnn-ci-pipeline.yml @@ -32,7 +32,7 @@ parameters: - name: QnnSdk displayName: QNN SDK version type: string - default: 2.24.0.240626 + default: 2.25.0.240728 jobs: - job: 'build' From 4ad87ca2e11f124540b93d48f3688c897d0376cf Mon Sep 17 00:00:00 2001 From: Edward Chen <18449977+edgchen1@users.noreply.github.com> Date: Tue, 6 Aug 2024 12:42:57 -0700 Subject: [PATCH 09/15] Fix usability checker CoreML config file path. (#21626) Fix usability checker CoreML config file path. The files got renamed but one place was still referring to the old name. --- tools/python/util/mobile_helpers/usability_checker.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/python/util/mobile_helpers/usability_checker.py b/tools/python/util/mobile_helpers/usability_checker.py index a8b5021f1387b..e7948c43baa49 100644 --- a/tools/python/util/mobile_helpers/usability_checker.py +++ b/tools/python/util/mobile_helpers/usability_checker.py @@ -513,11 +513,11 @@ def check_nnapi_partitions(model, require_fixed_input_sizes: bool): return _check_ep_partitioning(model, config_path, require_fixed_input_sizes) -def check_coreml_partitions(model: onnx.ModelProto, require_fixed_input_sizes: bool, config_filename): +def check_coreml_partitions(model: onnx.ModelProto, require_fixed_input_sizes: bool, config_filename: str): # if we're running in the ORT python package the file should be local. otherwise assume we're running from the # ORT repo script_dir = pathlib.Path(__file__).parent - local_config = script_dir / "coreml_supported_ops.md" + local_config = script_dir / config_filename if local_config.exists(): config_path = local_config else: From b95aa0563ff99cfcda3f036fe11d8aeecb3539a1 Mon Sep 17 00:00:00 2001 From: duanshengliu <44742794+duanshengliu@users.noreply.github.com> Date: Wed, 7 Aug 2024 07:23:20 +0800 Subject: [PATCH 10/15] Improve speed in combining per-channel data (#21563) ### Description Improve speed in combining `per-channel` data for using a single `np.concatenate` instead of multiple `np.concatenates` within a for loop. ### Motivation and Context Fix the issue https://github.com/microsoft/onnxruntime/issues/21562 Signed-off-by: duansheng.liu <44742794+duanshengliu@users.noreply.github.com> --- .../python/tools/quantization/base_quantizer.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/onnxruntime/python/tools/quantization/base_quantizer.py b/onnxruntime/python/tools/quantization/base_quantizer.py index 2f197cc7f31c0..aab04485246d6 100644 --- a/onnxruntime/python/tools/quantization/base_quantizer.py +++ b/onnxruntime/python/tools/quantization/base_quantizer.py @@ -418,6 +418,9 @@ def quantize_weight_per_channel_impl( zero_point_list = [] scale_list = [] quantized_per_channel_data_list = [] + weights_shape = list(weights.shape) + reshape_dims = list(weights_shape) # deep copy + reshape_dims[channel_axis] = 1 # only one per channel for reshape for i in range(channel_count): per_channel_data = weights.take(i, channel_axis) channel_override_index = i if i < num_channel_overrides else 0 @@ -460,17 +463,10 @@ def quantize_weight_per_channel_impl( zero_point_list.append(zero_point) scale_list.append(scale) - quantized_per_channel_data_list.append(quantized_per_channel_data) + quantized_per_channel_data_list.append(np.asarray(quantized_per_channel_data).reshape(reshape_dims)) # combine per_channel_data into one - weights_shape = list(weights.shape) - reshape_dims = list(weights_shape) # deep copy - reshape_dims[channel_axis] = 1 # only one per channel for reshape - quantized_weights = np.asarray(quantized_per_channel_data_list[0]).reshape(reshape_dims) - for i in range(1, len(quantized_per_channel_data_list)): - channel_weights = np.asarray(quantized_per_channel_data_list[i]).reshape(reshape_dims) - quantized_weights = np.concatenate((quantized_weights, channel_weights), channel_axis) - + quantized_weights = np.concatenate(quantized_per_channel_data_list, channel_axis) q_weight_name = weight_name + TENSOR_NAME_QUANT_SUFFIX zp_name = weight_name + "_zero_point" scale_name = weight_name + "_scale" From 621b16f47870b0fcbd113a37c589f46cea5a69a3 Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Wed, 7 Aug 2024 17:47:15 +0800 Subject: [PATCH 11/15] Pin transformer and optimum version (#21650) ### Description ### Motivation and Context To fix whisper test failure --- .../python/tools/transformers/models/whisper/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/onnxruntime/python/tools/transformers/models/whisper/requirements.txt b/onnxruntime/python/tools/transformers/models/whisper/requirements.txt index 689b14ea9a684..979f872ac4c5e 100644 --- a/onnxruntime/python/tools/transformers/models/whisper/requirements.txt +++ b/onnxruntime/python/tools/transformers/models/whisper/requirements.txt @@ -1,11 +1,11 @@ torch>=1.13.0 -transformers>=4.24.0 +transformers>=4.24.0,<= 4.42.4 openai-whisper>=20231117 ffmpeg-python datasets soundfile librosa -optimum +optimum<=1.21.2 onnxruntime-extensions>=0.9.0 onnx==1.16.1 protobuf==3.20.2 From c93b92a43f9b4bc66a5773e86e47f09bc1764807 Mon Sep 17 00:00:00 2001 From: Xiang Zhang Date: Wed, 7 Aug 2024 16:27:18 -0700 Subject: [PATCH 12/15] fix wrong check for tree ensemble regressor (#21595) Fix missed ORT_ENFORCE check which caused heap buffer overflow because of out of bound access. --- onnxruntime/core/providers/cpu/ml/tree_ensemble_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onnxruntime/core/providers/cpu/ml/tree_ensemble_common.h b/onnxruntime/core/providers/cpu/ml/tree_ensemble_common.h index 8f847fe66aa73..df27f888bb0af 100644 --- a/onnxruntime/core/providers/cpu/ml/tree_ensemble_common.h +++ b/onnxruntime/core/providers/cpu/ml/tree_ensemble_common.h @@ -172,7 +172,7 @@ Status TreeEnsembleCommon::Init( nodes_falsenodeids.size() == nodes_values_as_tensor.size()); ORT_ENFORCE(target_class_ids.size() == target_class_nodeids.size()); ORT_ENFORCE(target_class_ids.size() == target_class_treeids.size()); - ORT_ENFORCE(target_class_ids.size() == target_class_treeids.size()); + ORT_ENFORCE(target_class_weights.empty() || target_class_ids.size() == target_class_weights.size()); ORT_ENFORCE(base_values.empty() || base_values_as_tensor.empty()); ORT_ENFORCE(nodes_hitrates.empty() || nodes_hitrates_as_tensor.empty()); ORT_ENFORCE(nodes_values.empty() || nodes_values_as_tensor.empty()); From d616025884da05368c38270338b1ab3698e0ecb6 Mon Sep 17 00:00:00 2001 From: Scott McKay Date: Thu, 8 Aug 2024 10:29:15 +1000 Subject: [PATCH 13/15] Match changes in gh-pages PR (#21628) ### Description Update to match #21627 and make the info for Split consistent. As a Split that doesn't split anything is a no-op it doesn't seem meaningful to call that limitation out in the docs. ### Motivation and Context --- tools/ci_build/github/apple/coreml_supported_mlprogram_ops.md | 2 +- .../ci_build/github/apple/coreml_supported_neuralnetwork_ops.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/ci_build/github/apple/coreml_supported_mlprogram_ops.md b/tools/ci_build/github/apple/coreml_supported_mlprogram_ops.md index b546c266c131b..25881d9ee9f88 100644 --- a/tools/ci_build/github/apple/coreml_supported_mlprogram_ops.md +++ b/tools/ci_build/github/apple/coreml_supported_mlprogram_ops.md @@ -24,7 +24,7 @@ Keep in sync with doco generated from /docs/execution-providers/CoreML-Execution |ai.onnx:Reshape|| |ai.onnx:Resize|See [resize_op_builder.cc](https://github.com/microsoft/onnxruntime/blob/main/onnxruntime/core/providers/coreml/builders/impl/resize_op_builder.cc) implementation. There are too many permutations to describe the valid combinations.| |ai.onnx.Slice|starts/ends/axes/steps must be constant initializers.| -|ai.onnx:Split|| +|ai.onnx:Split|If provided, `splits` must be constant.| |ai.onnx:Sub|| |ai.onnx:Sigmoid|| |ai:onnx:Tanh|| diff --git a/tools/ci_build/github/apple/coreml_supported_neuralnetwork_ops.md b/tools/ci_build/github/apple/coreml_supported_neuralnetwork_ops.md index 53a992827e637..b9d636a5b0ccb 100644 --- a/tools/ci_build/github/apple/coreml_supported_neuralnetwork_ops.md +++ b/tools/ci_build/github/apple/coreml_supported_neuralnetwork_ops.md @@ -35,7 +35,7 @@ Keep in sync with doco generated from /docs/execution-providers/CoreML-Execution |ai.onnx:Sigmoid|| |ai.onnx:Slice|Inputs `starts`, `ends`, `axes`, and `steps` should be constant. Empty slice is not supported.| |ai.onnx:Softmax|| -|ai.onnx:Split|If provided, `splits` should be constant. num of outputs supported is at least 2.| +|ai.onnx:Split|If provided, `splits` must be constant.| |ai.onnx:Squeeze|| |ai.onnx:Sqrt|| |ai.onnx:Sub|| From 5e66fcc703c6dc84e035923a5e018f177c3a1f4a Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Thu, 8 Aug 2024 09:56:37 -0700 Subject: [PATCH 14/15] [js/web] allow op test to use f16 type for inputs/outputs (#21664) ### Description allow op test to use f16 type for inputs/outputs. This PR introduces "@petamoriken/float16" as Float16Array polyfill but restricts it to be only used for test runner. --- js/web/package-lock.json | 13 ++++++ js/web/package.json | 1 + js/web/test/data/ops/pad_f16.jsonc | 74 ++++++++++++++++++++++++++++++ js/web/test/op-test-schema.json | 4 ++ js/web/test/test-runner.ts | 29 +++++++++++- 5 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 js/web/test/data/ops/pad_f16.jsonc diff --git a/js/web/package-lock.json b/js/web/package-lock.json index 1d3b7f161c287..d37cf6bd90887 100644 --- a/js/web/package-lock.json +++ b/js/web/package-lock.json @@ -18,6 +18,7 @@ }, "devDependencies": { "@chiragrupani/karma-chromium-edge-launcher": "^2.2.2", + "@petamoriken/float16": "^3.8.7", "@types/chai": "^4.3.4", "@types/emscripten": "^1.39.6", "@types/flatbuffers": "^1.10.0", @@ -127,6 +128,12 @@ "node": ">= 8" } }, + "node_modules/@petamoriken/float16": { + "version": "3.8.7", + "resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.8.7.tgz", + "integrity": "sha512-/Ri4xDDpe12NT6Ex/DRgHzLlobiQXEW/hmG08w1wj/YU7hLemk97c+zHQFp0iZQ9r7YqgLEXZR2sls4HxBf9NA==", + "dev": true + }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -3589,6 +3596,12 @@ "fastq": "^1.6.0" } }, + "@petamoriken/float16": { + "version": "3.8.7", + "resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.8.7.tgz", + "integrity": "sha512-/Ri4xDDpe12NT6Ex/DRgHzLlobiQXEW/hmG08w1wj/YU7hLemk97c+zHQFp0iZQ9r7YqgLEXZR2sls4HxBf9NA==", + "dev": true + }, "@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", diff --git a/js/web/package.json b/js/web/package.json index 11e18a5ae1705..94dd047915b05 100644 --- a/js/web/package.json +++ b/js/web/package.json @@ -36,6 +36,7 @@ ], "devDependencies": { "@chiragrupani/karma-chromium-edge-launcher": "^2.2.2", + "@petamoriken/float16": "^3.8.7", "@types/chai": "^4.3.4", "@types/emscripten": "^1.39.6", "@types/flatbuffers": "^1.10.0", diff --git a/js/web/test/data/ops/pad_f16.jsonc b/js/web/test/data/ops/pad_f16.jsonc new file mode 100644 index 0000000000000..44c61b8a95382 --- /dev/null +++ b/js/web/test/data/ops/pad_f16.jsonc @@ -0,0 +1,74 @@ +[ + { + "name": "constant 2D float16", + "operator": "Pad", + "opset": { "domain": "", "version": 10 }, + "attributes": [ + { "name": "mode", "data": "constant", "type": "string" }, + { "name": "value", "data": 1.2, "type": "float" }, + { "name": "pads", "data": [3, 2, 2, 3], "type": "ints" } + ], + "cases": [ + { + "name": "[2,2]->[7,7]", + "inputs": [ + { + "data": [1.0, 2.0, 3.0, 4.5], + "dims": [2, 2], + "type": "float16" + } + ], + "outputs": [ + { + "data": [ + 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.0, 2.0, 1.2, 1.2, 1.2, 1.2, 1.2, 3.0, 4.5, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 + ], + "dims": [7, 7], + "type": "float16" + } + ] + } + ] + }, + { + "name": "constant 2D float16", + "operator": "Pad", + "opset": { "domain": "", "version": 19 }, + "attributes": [{ "name": "mode", "data": "constant", "type": "string" }], + "cases": [ + { + "name": "[2,2]->[7,7]", + "inputs": [ + { + "data": [1.0, 2.0, 3.0, 4.5], + "dims": [2, 2], + "type": "float16" + }, + { + "data": [3, 2, 2, 3], + "dims": [4], + "type": "int64" + }, + { + "data": [1.2], + "dims": [1], + "type": "float16" + } + ], + "outputs": [ + { + "data": [ + 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.0, 2.0, 1.2, 1.2, 1.2, 1.2, 1.2, 3.0, 4.5, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2 + ], + "dims": [7, 7], + "type": "float16" + } + ] + } + ] + } +] diff --git a/js/web/test/op-test-schema.json b/js/web/test/op-test-schema.json index d6eab6a4ba7bc..0a0a691c37022 100644 --- a/js/web/test/op-test-schema.json +++ b/js/web/test/op-test-schema.json @@ -177,6 +177,7 @@ "properties": { "type": { "enum": [ + "float16", "float32", "float64", "int8", @@ -213,6 +214,7 @@ "properties": { "type": { "enum": [ + "float16", "float32", "float64", "int8", @@ -247,6 +249,7 @@ "properties": { "type": { "enum": [ + "float16", "float32", "float64", "int8", @@ -283,6 +286,7 @@ "properties": { "type": { "enum": [ + "float16", "float32", "float64", "int8", diff --git a/js/web/test/test-runner.ts b/js/web/test/test-runner.ts index e1dd7bbe1967b..bc782a18c55f2 100644 --- a/js/web/test/test-runner.ts +++ b/js/web/test/test-runner.ts @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +import {Float16Array as Float16ArrayPolyfill} from '@petamoriken/float16'; import {expect} from 'chai'; import * as ort from 'onnxruntime-common'; import {extname} from 'path'; @@ -391,6 +392,24 @@ export class TensorResultValidator { case 'string': return this.strictEqual(actual.data, expected.data); + case 'float16': { + const actualData = actual.data as Uint16Array; + const actualDataBuffer = actualData.buffer; + const actualDataByteOffset = actualData.byteOffset; + const actualDataLength = actualData.length; + const actualDataFloat32Array = + new Float32Array(new Float16ArrayPolyfill(actualDataBuffer, actualDataByteOffset, actualDataLength)); + + const expectedData = expected.data as Uint16Array; + const expectedDataBuffer = expectedData.buffer; + const expectedDataByteOffset = expectedData.byteOffset; + const expectedDataLength = expectedData.length; + const expectedDataFloat32Array = + new Float32Array(new Float16ArrayPolyfill(expectedDataBuffer, expectedDataByteOffset, expectedDataLength)); + + return this.floatEqual(actualDataFloat32Array, expectedDataFloat32Array); + } + case 'float32': case 'float64': return this.floatEqual( @@ -919,11 +938,14 @@ async function runProtoOpTestcase( const fetches: Record> = {}; testCase.inputs.forEach((input, i) => { if (input.data) { - let data: number[]|BigUint64Array|BigInt64Array = input.data; + let data: number[]|BigUint64Array|BigInt64Array|Uint16Array = input.data; if (input.type === 'uint64') { data = BigUint64Array.from(input.data.map(BigInt)); } else if (input.type === 'int64') { data = BigInt64Array.from(input.data.map(BigInt)); + } else if (input.type === 'float16') { + const dataArr = Float16ArrayPolyfill.from(input.data); + data = new Uint16Array(dataArr.buffer, dataArr.byteOffset, dataArr.byteLength / 2); } feeds[`input_${i}`] = new ort.Tensor(input.type, data, input.dims); } @@ -933,11 +955,14 @@ async function runProtoOpTestcase( const expectedOutputNames: string[] = []; testCase.outputs.forEach((output, i) => { if (output.data) { - let data: number[]|BigUint64Array|BigInt64Array = output.data; + let data: number[]|BigUint64Array|BigInt64Array|Uint16Array = output.data; if (output.type === 'uint64') { data = BigUint64Array.from(output.data.map(BigInt)); } else if (output.type === 'int64') { data = BigInt64Array.from(output.data.map(BigInt)); + } else if (output.type === 'float16') { + const dataArr = Float16ArrayPolyfill.from(output.data); + data = new Uint16Array(dataArr.buffer, dataArr.byteOffset, dataArr.byteLength / 2); } outputs.push(new ort.Tensor(output.type, data, output.dims)); expectedOutputNames.push(`output_${i}`); From a46e49b4399bb4d268aaa92f58f0a273fb02db9f Mon Sep 17 00:00:00 2001 From: Tianlei Wu Date: Thu, 8 Aug 2024 19:44:15 -0700 Subject: [PATCH 15/15] Unblock migraphx and linux GPU training ci pipelines (#21662) ### Description * Fix migraphx build error caused by https://github.com/microsoft/onnxruntime/pull/21598: Add a conditional compile on code block that depends on ROCm >= 6.2. Note that the pipeline uses ROCm 6.0. Unblock orttraining-linux-gpu-ci-pipeline and orttraining-ortmodule-distributed and orttraining-amd-gpu-ci-pipeline pipelines: * Disable a model test in linux GPU training ci pipelines caused by https://github.com/microsoft/onnxruntime/pull/19470: Sometime, cudnn frontend throws exception that cudnn graph does not support a Conv node of keras_lotus_resnet3D model on V100 GPU. Note that same test does not throw exception in other GPU pipelines. The failure might be related to cudnn 8.9 and V100 GPU used in the pipeline (Amper GPUs and cuDNN 9.x do not have the issue). The actual fix requires fallback logic, which will take time to implement, so we temporarily disable the test in training pipelines. * Force install torch for cuda 11.8. (The docker has torch 2.4.0 for cuda 12.1 to build torch extension, which it is not compatible cuda 11.8). Note that this is temporary walkround. More elegant fix is to make sure right torch version in docker build step, that might need update install_python_deps.sh and corresponding requirements.txt. * Skip test_gradient_correctness_conv1d since it causes segment fault. Root cause need more investigation (maybe due to cudnn frontend as well). * Skip test_aten_attention since it causes assert failure. Root cause need more investigation (maybe due to torch version). * Skip orttraining_ortmodule_distributed_tests.py since it has error that compiler for torch extension does not support c++17. One possible fix it to set the following compile argument inside setup.py of extension fused_adam: extra_compile_args['cxx'] = ['-std=c++17']. However, due to the urgency of unblocking the pipelines, just disable the test for now. * skip test_softmax_bf16_large. For some reason, torch.cuda.is_bf16_supported() returns True in V100 with torch 2.3.1, so the test was run in CI, but V100 does not support bf16 natively. * Fix typo of deterministic ### Motivation and Context --- .../providers/migraphx/migraphx_execution_provider.cc | 5 +++++ onnxruntime/test/onnx/TestCase.cc | 4 ++++ .../test/python/orttraining_test_ortmodule_api.py | 10 +++++++--- .../test/python/orttraining_test_ortmodule_onnx_ops.py | 2 ++ ...inux-gpu-ortmodule-distributed-test-ci-pipeline.yml | 2 +- .../orttraining-linux-gpu-test-ci-pipeline.yml | 4 ++-- 6 files changed, 21 insertions(+), 6 deletions(-) diff --git a/onnxruntime/core/providers/migraphx/migraphx_execution_provider.cc b/onnxruntime/core/providers/migraphx/migraphx_execution_provider.cc index 314e278695c49..4f7643d923fac 100644 --- a/onnxruntime/core/providers/migraphx/migraphx_execution_provider.cc +++ b/onnxruntime/core/providers/migraphx/migraphx_execution_provider.cc @@ -17,6 +17,7 @@ #include "migraphx_allocator.h" #include "gpu_data_transfer.h" #include "migraphx_inc.h" +#include #include "migraphx_stream_handle.h" @@ -1299,7 +1300,11 @@ Status MIGraphXExecutionProvider::Compile(const std::vector& if (!input_shape_match) { if (!load_precompiled_model(prog, load_compiled_model_, std::string{load_compiled_path_})) { LOGS_DEFAULT(VERBOSE) << "No Input shapes mismatch detected. Recompiling" << std::endl; +#ifndef ENABLE_TRAINING_CORE +#if HIP_VERSION_MAJOR > 6 || (HIP_VERSION_MAJOR == 6 && HIP_VERSION_MINOR >= 2) cmp_options.set_external_data_path(model_path_.has_parent_path() ? model_path_.parent_path().string() : std::filesystem::current_path().string()); +#endif +#endif prog = migraphx::parse_onnx_buffer(onnx_string, cmp_options); // Read in the calibration data and map it to an migraphx paramater map for the calibration ops diff --git a/onnxruntime/test/onnx/TestCase.cc b/onnxruntime/test/onnx/TestCase.cc index 3319fdd34646b..45aaca1ceae56 100644 --- a/onnxruntime/test/onnx/TestCase.cc +++ b/onnxruntime/test/onnx/TestCase.cc @@ -1035,6 +1035,10 @@ std::unique_ptr> GetBrokenTests(const std::string& provider // std::set broken_tests_keyword_set = {}; if (provider_name == "cuda") { +#ifdef ENABLE_TRAINING_CORE + // cudnn frontend exception in orttraining-linux-gpu-ci-pipeline. + broken_tests->insert({"keras_lotus_resnet3D", "Temporarily disabled pending investigation", {}}); +#endif #ifdef _WIN32 broken_tests->insert({"LSTM_Seq_lens_unpacked", "this test fails with new image since Aug 25."}); broken_tests->insert({"bidaf", "this test fails with new image since Aug 25."}); diff --git a/orttraining/orttraining/test/python/orttraining_test_ortmodule_api.py b/orttraining/orttraining/test/python/orttraining_test_ortmodule_api.py index 3615a12705241..0ab441ac936fe 100644 --- a/orttraining/orttraining/test/python/orttraining_test_ortmodule_api.py +++ b/orttraining/orttraining/test/python/orttraining_test_ortmodule_api.py @@ -779,6 +779,8 @@ def run_step(model, rerouted_output, dispatch_mask, expert_output): @pytest.mark.parametrize("input_requires_grad", [False, True]) @pytest.mark.parametrize("conv_algo_search", [None, "EXHAUSTIVE", "HEURISTIC"]) def test_gradient_correctness_conv1d(use_fp16, input_requires_grad, conv_algo_search): + pytest.skip("Temporarily disabled pending investigation (might be related to cudnn frontend).") + class NeuralNetConv1D(torch.nn.Module): def __init__(self, in_channels, out_channels, kernel_size, padding=0, groups=1): super().__init__() @@ -6044,7 +6046,7 @@ def test_e2e_padding_elimination(): torch.manual_seed(seed) torch.cuda.manual_seed(seed) torch.cuda.manual_seed_all(seed) - torch.backends.cudnn.determinstic = True + torch.backends.cudnn.deterministic = True torch.backends.cudnn.benchmark = False class OneLayer(torch.nn.Module): @@ -6773,7 +6775,7 @@ def forward(self, x): del os.environ["ORTMODULE_ALLOW_AUTOGRAD_CHECKPOINT"] -def test_layerwise_recompute_pythonop_determinstic(): +def test_layerwise_recompute_pythonop_deterministic(): original_val = os.environ.get("ORTMODULE_MEMORY_OPT_LEVEL", None) @@ -6887,7 +6889,7 @@ def generate_inputs(batch_size, max_seq_length, vocab_size): os.environ["ORTMODULE_MEMORY_OPT_LEVEL"] = "0" ort_model1 = ORTModule(copy.deepcopy(pt_model)) - torch.backends.cudnn.determinstic = True + torch.backends.cudnn.deterministic = True torch.backends.cudnn.benchmark = False pt_input, pt_mask = generate_inputs(batch_size, max_seq_length, vocab_size) @@ -6960,6 +6962,8 @@ def generate_inputs(batch_size, max_seq_length, vocab_size): reason="torch.nn.attention module was introduced in PyTorch 2.3.0", ) def test_aten_attention(): + pytest.skip("Temporarily disabled pending investigation.") + from torch.nn.attention import SDPBackend, sdpa_kernel class _NeuralNetAttention(torch.nn.Module): diff --git a/orttraining/orttraining/test/python/orttraining_test_ortmodule_onnx_ops.py b/orttraining/orttraining/test/python/orttraining_test_ortmodule_onnx_ops.py index 537dcd2ccdb09..35e5bae3ea67e 100644 --- a/orttraining/orttraining/test/python/orttraining_test_ortmodule_onnx_ops.py +++ b/orttraining/orttraining/test/python/orttraining_test_ortmodule_onnx_ops.py @@ -150,6 +150,8 @@ def test_onnx_ops(self): @unittest.skipIf(not torch.cuda.is_bf16_supported(), "Test requires CUDA and BF16 support") def test_softmax_bf16_large(self): + raise unittest.SkipTest("Temporarily disabled pending investigation") + if torch.version.cuda is None: # Only run this test when CUDA is available, as on ROCm BF16 is not supported by MIOpen. return diff --git a/tools/ci_build/github/azure-pipelines/orttraining-linux-gpu-ortmodule-distributed-test-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/orttraining-linux-gpu-ortmodule-distributed-test-ci-pipeline.yml index 82aa7b24e7be9..da40be43048c2 100644 --- a/tools/ci_build/github/azure-pipelines/orttraining-linux-gpu-ortmodule-distributed-test-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/orttraining-linux-gpu-ortmodule-distributed-test-ci-pipeline.yml @@ -71,7 +71,7 @@ stages: --volume $(Build.BinariesDirectory):/build \ --volume $(Agent.TempDirectory)/mnist:/mnist \ onnxruntime_ortmodule_distributed_tests_image \ - bash -c "rm -rf /build/RelWithDebInfo/onnxruntime/ && python3 -m pip install /build/RelWithDebInfo/dist/onnxruntime*.whl && python3 -m onnxruntime.training.ortmodule.torch_cpp_extensions.install && /build/RelWithDebInfo/launch_test.py --cmd_line_with_args 'python orttraining_ortmodule_distributed_tests.py --mnist /mnist' --cwd /build/RelWithDebInfo" \ + bash -c "rm -rf /build/RelWithDebInfo/onnxruntime/ && python3 -m pip install /build/RelWithDebInfo/dist/onnxruntime*.whl && python3 -m pip install torch==2.3.1+cu118 --index-url https://download.pytorch.org/whl/cu118 && python3 -m onnxruntime.training.ortmodule.torch_cpp_extensions.install && echo temporarily skip /build/RelWithDebInfo/launch_test.py --cmd_line_with_args 'python orttraining_ortmodule_distributed_tests.py --mnist /mnist' --cwd /build/RelWithDebInfo" \ displayName: 'Run orttraining_ortmodule_distributed_tests.py' condition: succeededOrFailed() timeoutInMinutes: 30 diff --git a/tools/ci_build/github/azure-pipelines/templates/orttraining-linux-gpu-test-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/templates/orttraining-linux-gpu-test-ci-pipeline.yml index f832315c1f0df..5f073433265fa 100644 --- a/tools/ci_build/github/azure-pipelines/templates/orttraining-linux-gpu-test-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/templates/orttraining-linux-gpu-test-ci-pipeline.yml @@ -21,7 +21,7 @@ steps: --volume $(Build.BinariesDirectory)/${{ parameters.BuildConfig }}:/build \ --volume $(Agent.TempDirectory)/mnist:/mnist \ ${{ parameters.DockerImageTag }} \ - bash -c "rm -rf /build/onnxruntime/ && python3 -m pip install /build/dist/onnxruntime*.whl && python3 -m onnxruntime.training.ortmodule.torch_cpp_extensions.install && /build/launch_test.py --cmd_line_with_args 'python orttraining_ortmodule_tests.py --mnist /mnist --bert_data /bert_data/hf_data/glue_data/CoLA/original/raw' --cwd /build" \ + bash -c "rm -rf /build/onnxruntime/ && python3 -m pip show torch && python3 -m pip install torch==2.3.1+cu118 --index-url https://download.pytorch.org/whl/cu118 && python3 -m pip install /build/dist/onnxruntime*.whl && python3 -m onnxruntime.training.ortmodule.torch_cpp_extensions.install && /build/launch_test.py --cmd_line_with_args 'python orttraining_ortmodule_tests.py --mnist /mnist --bert_data /bert_data/hf_data/glue_data/CoLA/original/raw' --cwd /build" \ displayName: 'Run orttraining_ortmodule_tests.py' condition: succeededOrFailed() timeoutInMinutes: 60 @@ -35,7 +35,7 @@ steps: --volume $(Build.SourcesDirectory):/onnxruntime_src \ --volume $(Build.BinariesDirectory)/${{ parameters.BuildConfig }}:/build \ ${{ parameters.DockerImageTag }} \ - bash -c "rm -rf /build/onnxruntime/ && python3 -m pip install /build/dist/onnxruntime*.whl && /build/launch_test.py --cmd_line_with_args 'python orttraining_test_ort_apis.py --cwd /build' --cwd /build" \ + bash -c "rm -rf /build/onnxruntime/ && python3 -m pip install /build/dist/onnxruntime*.whl && python3 -m pip install torch==2.3.1+cu118 --index-url https://download.pytorch.org/whl/cu118 && /build/launch_test.py --cmd_line_with_args 'python orttraining_test_ort_apis.py --cwd /build' --cwd /build" \ displayName: 'Run ORT Training APIs Tests' condition: succeededOrFailed() timeoutInMinutes: 120